1. 程式人生 > 實用技巧 >python設計模式-結構模式

python設計模式-結構模式

III.結構模式

1.代理模式

  • 代理模式,一個類代表另一個類功能,在代理模式中,我們建立具有現有物件的物件,以便向外界提供功能介面。

    class SensitiveInfo:
        def __init__(self):
            self.users = ["nick","tom","ben","mike"]
        def read(self):
            print("the username is {}".format(' '.join(self.users)))
        def add(self,user):
            self.users.append(user)
            print("add user {}".format(user))
    
    class Info:
        def __init__(self):
            self.protected = SensitiveInfo()
            self.secret = "123456"
        def read(self):
            self.protected.read()
    
        def add(self, user):
            sec = input('what is the secret? ')
            self.protected.add(user) if sec == self.secret else print("That's wrong!")
    
    def main():
        info = Info()
        while True:
            print('1. read list |==| 2. add user |==| 3. quit')
            key = input('choose option: ')
            if key == '1':
                info.read()
            elif key == '2':
                name = input('choose username: ')
                info.add(name)
            elif key == '3':
                exit()
            else:
                print('unknown option: {}'.format(key))
    
    if __name__ == '__main__':
        main()
    
    

2.外觀模式

  • 隱藏系統複雜性,向客戶端提供一個客戶端可以訪問系統介面。向現有系統新增一個介面,來隱藏系統複雜性。這種模式涉及到一個單一的類,該類提供了客戶端請求的簡化方法和對現有系統類方法的委託呼叫。
class A:
    def run(self):
        print('A run')

    def jump(self):
        print('A jump')


class B:
    def run(self):
        print('B run')

    def jump(self):
        print('B jump')


class C:
    def run(self):
        print('C run')

    def jump(self):
        print('C jump')

class Facade:
    def __init__(self):
        self.a = A()
        self.b = B()
        self.c = C()
    def run(self):
        for item in ("a","b","c"):
            obj = getattr(self,item)
            obj.run()

    def jump(self):
        for item in ("a","b","c"):
            getattr(self,item).jump()
if __name__ == '__main__':
    facade = Facade()
    facade.run()
    facade.jump()

3.橋接模式

  • 在python程式設計中,橋接指的是抽象部分和實體部分的連線,簡單來說是類和類例項化過程中連結。
class A:
    def run(self,name):
        print("my name is {}".format(name))

class B:
    def run(self, name):
        print("我的名字是:{}".format(name))

class Bridge:
    def __init__(self, ager, classname):
        self.ager = ager
        self.classname = classname

    def bridge_run(self):
        self.classname.run(self.ager)
if __name__ == '__main__':
    test = Bridge('Tom', A())
    test.bridge_run()

4.組合模式

  • 用於把一組相似物件當作一個單一的物件,組合模式依據樹形結構來組合物件。您想表示物件的部分-整體層次結構(樹形結構)。 2、您希望使用者忽略組合物件與單個物件的不同,使用者將統一地使用組合結構中的所有物件。
class Company:
    name = ''

    def __init__(self, name):
        self.name = name

    def add(self, company):
        pass

    def remove(self, company):
        pass

    def display(self, depth):
        pass

    def line_of_duty(self):  # 履行職責
        pass

    # Composite:公司類
class ConcreteCompany(Company):
    childrenCompany = None

    def __init__(self, name):
        Company.__init__(self, name)
        self.childrenCompany = []

    def add(self, company):
        self.childrenCompany.append(company)

    def remove(self, company):
        self.childrenCompany.remove(company)

    def display(self, depth):
        print('-' * depth + self.name)

        for component in self.childrenCompany:
            component.display(depth + 2)

    def line_of_duty(self):  # 履行職責
        for component in self.childrenCompany:
            component.line_of_duty()

# Leaf:具體職能部門
class HRDepartment(Company):
    def __init__(self, name):
        Company.__init__(self, name)

    def display(self, depth):
        print('-' * depth + self.name)

    def line_of_duty(self):  # 履行職責
        print('%s\t員工招聘培訓管理' % self.name)


# Leaf:具體職能部門
class FinanceDepartment(Company):
    def __init__(self, name):
        Company.__init__(self, name)

    def display(self, depth):
        print('-' * depth + self.name)

    def line_of_duty(self):  # 履行職責
        print('%s\t公司財務收支管理' % self.name)

if __name__ == '__main__':
    root = ConcreteCompany('北京總公司')
    root.add(HRDepartment('總公司人力資源部'))
    root.add(FinanceDepartment('總公司財務部'))

    comp = ConcreteCompany('華東分公司')
    comp.add(HRDepartment('華東分公司人力資源部'))
    comp.add(FinanceDepartment('華東分公司財務部'))
    root.add(comp)

    comp1 = ConcreteCompany('南京辦事處')
    comp1.add(HRDepartment('南京辦事處人力資源部'))
    comp1.add(FinanceDepartment('南京辦事處財務部'))
    comp.add(comp1)

    comp2 = ConcreteCompany('杭州辦事處')
    comp2.add(HRDepartment('杭州辦事處人力資源部'))
    comp2.add(FinanceDepartment('杭州辦事處財務部'))
    comp.add(comp2)

    print('-------公司結構圖-------')
    root.display(1)

    print('\n-------職責-------')
    root.line_of_duty()


5.裝飾者模式--函式裝飾器

import time
from functools import wraps

def timethis(func):
    '''
    Decorator that reports the execution time.
    '''

    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(func.__name__, end - start)
        return result

    return wrapper


@timethis
def fun():
    time.sleep(3)
    return 1


if __name__ == '__main__':
    fun()

6.裝飾者模式--類裝飾器

class Spam:
	@profiled
	def bar(self,x)
		print(self,x)
  • 我們想給一個物件新增額外功能,可以通過裝飾器,繼承或是組合方式,相比繼承,它會使程式碼更難去複用,繼承關係是靜態的。
# 修飾器裝飾
class Foo:
    def f1(self):
        print("original f1")

    def f2(self):
        print("original f2")


class Foo_decorator:
    def __init__(self, decoratee):
        self._decoratee = decoratee

    def f1(self):
        print("before run f1")
        self._decoratee.f1()
        print("after run f1")

    def __getattr__(self, name):
        return getattr(self._decoratee, name)

if __name__ == '__main__':
    u = Foo()
    v = Foo_decorator(u)
    v.f1()
    v.f2()

7.介面卡模式

  • 做為兩個介面是否相容的橋樑,這種模式涉及到一個單一的類,該類負責加入獨立的或不相容的介面功能。舉個真實的例子,讀卡器是作為記憶體卡和筆記本之間的介面卡。您將記憶體卡插入讀卡器,再將讀卡器插入筆記本,這樣就可以通過筆記本來讀取記憶體卡。
class Dog:
    def __init__(self, name):
        self.name = name

    def wangwang(self):
        print('my name is' + self.name + '。。。汪汪汪。。。')

    def dog_run(self):
        print(f'{self.name} is running')

class Cat:
    def __init__(self, name):
        self.name = name

    def miaomiao(self):
        print('my name is' + self.name + '。。。喵喵喵。。。')

    def cat_run(self):
        print(f'{self.name} is running')

class Sheep:
    def __init__(self, name):
        self.name = name

    def miemie(self):
        print('my name is' + self.name + '。。。咩咩。。。')

    def sheet_run(self):
        print(f'{self.name} is running')

class Adapter:
    def __init__(self, adapted_methods):

        self.__dict__.update(adapted_methods)

    def speak(self):
        pass

    def run(self):
        pass

def main():
    animals = []
    dog = Dog('旺財')
    cat = Cat('大臉貓')
    sheep = Sheep('喜洋洋')
    animals.append(Adapter({'speak': dog.wangwang, 'run': dog.dog_run}))
    animals.append(Adapter({'speak': cat.miaomiao, 'run': cat.cat_run}))
    animals.append(Adapter({'speak': sheep.miemie, 'run': sheep.sheet_run}))

    for a in animals:
        a.speak()
        a.run()
if __name__ == '__main__':
    main()