Python设计模式

  • 创建型模式,共 5 种:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式。

  • 结构型模式,共 7 种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

  • 行为型模式,共 11 种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

单例模式

class Singleton(object):
    """
    单例模式
    """
    class _A(object):
        """
       真正干活的类, 对外隐藏
        """
        def __init__(self):
            pass

        def display(self):
            """ 返回当前实例的 ID,是全局唯一的"""
            return id(self)

    # 类变量,用于存储 _A 的实例
    _instance = None

    def __init__(self):
        """ 先判断类变量中是否已经保存了 _A 的实例,如果没有则创建一个后返回"""
        if Singleton._instance is None:
            Singleton._instance = Singleton._A()

    def __getattr__(self, attr):
        """ 所有的属性都应该直接从 Singleton._instance 获取"""
        return getattr(self._instance, attr)


if __name__ == '__main__':
    # 创建两个实例
    s1 = Singleton()
    s2 = Singleton()
    print(id(s1), s1.display())
    print(id(s2), s2.display())

单例装饰器

class Singleton(object):
    """
    单例模式
    """
    class _A(object):
        """
       真正干活的类, 对外隐藏
        """
        def __init__(self):
            pass

        def display(self):
            """ 返回当前实例的 ID,是全局唯一的"""
            return id(self)

    # 类变量,用于存储 _A 的实例
    _instance = None

    def __init__(self):
        """ 先判断类变量中是否已经保存了 _A 的实例,如果没有则创建一个后返回"""
        if Singleton._instance is None:
            Singleton._instance = Singleton._A()

    def __getattr__(self, attr):
        """ 所有的属性都应该直接从 Singleton._instance 获取"""
        return getattr(self._instance, attr)


if __name__ == '__main__':
    # 创建两个实例
    s1 = Singleton()
    s2 = Singleton()
    print(id(s1), s1.display())
    print(id(s2), s2.display())
  • 工厂模式

原型模式 prototype

 1 import copy
 2 
 3 
 4 class Prototype:
 5     def __init__(self):
 6         self._objects = {}
 7 
 8     def register_object(self, name, obj):
 9         """Register an object"""
10         self._objects[name] = obj
11 
12     def unregister_object(self, name):
13         """Unregister an object"""
14         del self._objects[name]
15 
16     def clone(self, name, **attr):
17         """Clone a registered object and update inner attributes dictionary"""
18         obj = copy.deepcopy(self._objects.get(name))
19         obj.__dict__.update(attr)
20         return obj
21 
22 
23 def main():
24     class A:
25         pass
26 
27     a = A()
28     prototype = Prototype()
29     prototype.register_object('a', a)
30     b = prototype.clone('a', a=1, b=2, c=3)
31 
32     print(a)
33     print(b.a, b.b, b.c)
34 
35 
36 if __name__ == '__main__':
37     main()
View Code

装饰模式 decorator

 1 class foo(object):
 2     def f1(self):
 3         print("original f1")
 4 
 5     def f2(self):
 6         print("original f2")
 7 
 8 
 9 class foo_decorator(object):
10     def __init__(self, decoratee):
11         self._decoratee = decoratee
12 
13     def f1(self):
14         print("decorated f1")
15         self._decoratee.f1()
16 
17     def __getattr__(self, name):
18         return getattr(self._decoratee, name)
19 
20 u = foo()
21 v = foo_decorator(u)
22 v.f1()
23 v.f2()
View Code

 

 

行为型设计模式

  • 策略模式定义及简单实现案例
  • 观察者模式定义及简单实现案例
  • 命令模式定义及简单实现案例
  • 模板方法模式定义及简单实现案例

 

设计模式-结构型模式

mvc模型视图控制器模式

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
View(视图) - 视图代表模型包含的数据的可视化。
Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

quotes = ('A man is not complete until he is married. Then he is finished.',
          'As I said before, I never repeat myself.',
          'Behind a successful man is an exhausted woman.',
          'Black holes really suck...', 'Facts are stubborn things.')


class QuoteModel:

    def get_quote(self, n):
        try:
            value = quotes[n]
        except IndexError as err:
            value = 'Not found!'
        return value


class QuoteTerminalView:

    def show(self, quote):
        print('And the quote is: "{}"'.format(quote))

    def error(self, msg):
        print('Error: {}'.format(msg))

    def select_quote(self):
        return input('Which quote number would you like to see?')


class QuoteTerminalController:

    def __init__(self):
        self.model = QuoteModel()
        self.view = QuoteTerminalView()

    def run(self):
        valid_input = False
        while not valid_input:
            n = self.view.select_quote()
            try:
                n = int(n)
            except ValueError as err:
                self.view.error("Incorrect index '{}'".format(n))
            else:
                valid_input = True
        quote = self.model.get_quote(n)
        self.view.show(quote)


def main():
    controller = QuoteTerminalController()
    while True:
        controller.run()

if __name__ == '__main__':
    main()
View Code

代理模式

在某些应用中,我们想要在访问某个对象之前执行一个或多个重要的操作,例如,访问敏感信息——在允许用户访问敏感信息之前,我们希望确保用户具备足够的权限。操作系统中也存在类似的情况,用户必须具有管理员权限才能在系统中安装新程序。上面提到的重要操作不一定与安全问题相关。延迟初始化是另一个案例:我们想要把一个计算成本较高的对象的创建过程延迟到用户首次真正使用它时才进行。

 

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

# coding: utf-8


class SensitiveInfo:

    def __init__(self):
        self.users = ['nick', 'tom', 'ben', 'mike']

    def read(self):
        print('There are {} users: {}'.format(len(self.users), ' '.join(self.users)))

    def add(self, user):
        self.users.append(user)
        print('Added user {}'.format(user))


class Info:

    '''SensitiveInfo的保护代理'''

    def __init__(self):
        self.protected = SensitiveInfo()
        self.secret = '0xdeadbeef'

    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()
View Code

继承和代理都是代码复用的方式。
继承是把要复用的代码(即父对象)的所有属性和行为都复用。不管用得着用不着,先一鼓脑都继承过来。
代理是把要复用的对象作为自己的成员变量,然后在自己的方法中通过这个成员变量去调用要复用的对象的方法。这样就获得了要复用的对象的部分功能,而不用把要复用的对象的全部属性和方法都复用过来。可以称为部分继承或者方法借用模式。相比继承来说,更灵活。

责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

class Event:

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

    def __str__(self):
        return self.name


class Widget:

    def __init__(self, parent=None):
        self.parent = parent

    def handle(self, event):
        handler = 'handle_{}'.format(event)
        if hasattr(self, handler):
            method = getattr(self, handler)
            method(event)
        elif self.parent:
            self.parent.handle(event)
        elif hasattr(self, 'handle_default'):
            self.handle_default(event)


class MainWindow(Widget):

    def handle_close(self, event):
        print('MainWindow: {}'.format(event))

    def handle_default(self, event):
        print('MainWindow Default: {}'.format(event))


class SendDialog(Widget):

    def handle_paint(self, event):
        print('SendDialog: {}'.format(event))


class MsgText(Widget):

    def handle_down(self, event):
        print('MsgText: {}'.format(event))


def main():
    mw = MainWindow()
    sd = SendDialog(mw)
    msg = MsgText(sd)

    for e in ('down', 'paint', 'unhandled', 'close'):
        evt = Event(e)
        print('\nSending event -{}- to MainWindow'.format(evt))
        mw.handle(evt)
        print('Sending event -{}- to SendDialog'.format(evt))
        sd.handle(evt)
        print('Sending event -{}- to MsgText'.format(evt))
        msg.handle(evt)

if __name__ == '__main__':
    main()
View Code

命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

现在多数应用都有撤销操作。虽然难以想象,但在很多年里,任何软件中确实都不存在撤销,操作。撤销操作是在1974年引入的(请参考网页[t.cn/Rqr3N22]),但Fortran和Lisp分别早在1957,年和1958年就已创建了撤销操作(请参考网页[t.cn/Rqr3067]),这两门语言仍在被人广泛使用。在那些年里,我真心不想使用应用软件。犯了一个错误,用户也没什么便捷方式能修正它。

 1 import os
 2 
 3 verbose = True
 4 
 5 
 6 class RenameFile:
 7 
 8     def __init__(self, path_src, path_dest):
 9         self.src, self.dest = path_src, path_dest
10 
11     def execute(self):
12         if verbose:
13             print("[renaming '{}' to '{}']".format(self.src, self.dest))
14         os.rename(self.src, self.dest)
15 
16     def undo(self):
17         if verbose:
18             print("[renaming '{}' back to '{}']".format(self.dest, self.src))
19         os.rename(self.dest, self.src)
20 
21 
22 class CreateFile:
23 
24     def __init__(self, path, txt='hello world\n'):
25         self.path, self.txt = path, txt
26 
27     def execute(self):
28         if verbose:
29             print("[creating file '{}']".format(self.path))
30         with open(self.path, mode='w', encoding='utf-8') as out_file:
31             out_file.write(self.txt)
32 
33     def undo(self):
34         delete_file(self.path)
35 
36 
37 class ReadFile:
38 
39     def __init__(self, path):
40         self.path = path
41 
42     def execute(self):
43         if verbose:
44             print("[reading file '{}']".format(self.path))
45         with open(self.path, mode='r', encoding='utf-8') as in_file:
46             print(in_file.read(), end='')
47 
48 
49 def delete_file(path):
50     if verbose:
51         print("deleting file '{}'".format(path))
52     os.remove(path)
53 
54 
55 def main():
56     orig_name, new_name = 'file1', 'file2'
57 
58     commands = []
59     for cmd in CreateFile(orig_name), ReadFile(orig_name), RenameFile(orig_name, new_name):
60         commands.append(cmd)
61 
62     [c.execute() for c in commands]
63 
64     answer = input('reverse the executed commands? [y/n] ')
65 
66     if answer not in 'yY':
67         print("the result is {}".format(new_name))
68         exit()
69 
70     for c in reversed(commands):
71         try:
72             c.undo()
73         except AttributeError as e:
74             pass
75 
76 if __name__ == '__main__':
77     main()
View Code

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。有时,我们希望在一个对象的状态改变时更新另外一组对象。

 1 class Publisher:
 2 
 3     def __init__(self):
 4         self.observers = []
 5 
 6     def add(self, observer):
 7         if observer not in self.observers:
 8             self.observers.append(observer)
 9         else:
10             print('Failed to add: {}'.format(observer))
11 
12     def remove(self, observer):
13         try:
14             self.observers.remove(observer)
15         except ValueError:
16             print('Failed to remove: {}'.format(observer))
17 
18     def notify(self):
19         [o.notify(self) for o in self.observers]
20 
21 
22 class DefaultFormatter(Publisher):
23 
24     def __init__(self, name):
25         Publisher.__init__(self)
26         self.name = name
27         self._data = 0
28 
29     def __str__(self):
30         return "{}: '{}' has data = {}".format(type(self).__name__, self.name, self._data)
31 
32     @property
33     def data(self):
34         return self._data
35 
36     @data.setter
37     def data(self, new_value):
38         try:
39             self._data = int(new_value)
40         except ValueError as e:
41             print('Error: {}'.format(e))
42         else:
43             self.notify()
44 
45 
46 class HexFormatter:
47 
48     def notify(self, publisher):
49         print("{}: '{}' has now hex data = {}".format(type(self).__name__, publisher.name, hex(publisher.data)))
50 
51 
52 class BinaryFormatter:
53 
54     def notify(self, publisher):
55         print("{}: '{}' has now bin data = {}".format(type(self).__name__, publisher.name, bin(publisher.data)))
56 
57 
58 def main():
59     df = DefaultFormatter('test1')
60     print(df)
61 
62     print()
63     hf = HexFormatter()
64     df.add(hf)
65     df.data = 3
66     print(df)
67 
68     print()
69     bf = BinaryFormatter()
70     df.add(bf)
71     df.data = 21
72     print(df)
73 
74     print()
75     df.remove(hf)
76     df.data = 40
77     print(df)
78 
79     print()
80     df.remove(hf)
81     df.add(bf)
82     df.data = 'hello'
83     print(df)
84 
85     print()
86     df.data = 15.8
87     print(df)
88 
89 
90 if __name__ == '__main__':
91     main()
View Code

状态模式

在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。

在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。

 1 class State(object):
 2     """Base state. This is to share functionality"""
 3 
 4     def scan(self):
 5         """Scan the dial to the next station"""
 6         self.pos += 1
 7         if self.pos == len(self.stations):
 8             self.pos = 0
 9         print("Scanning... Station is", self.stations[self.pos], self.name)
10 
11 
12 class AmState(State):
13     def __init__(self, radio):
14         self.radio = radio
15         self.stations = ["1250", "1380", "1510"]
16         self.pos = 0
17         self.name = "AM"
18 
19     def toggle_amfm(self):
20         print("Switching to FM")
21         self.radio.state = self.radio.fmstate
22 
23 
24 class FmState(State):
25     def __init__(self, radio):
26         self.radio = radio
27         self.stations = ["81.3", "89.1", "103.9"]
28         self.pos = 0
29         self.name = "FM"
30 
31     def toggle_amfm(self):
32         print("Switching to AM")
33         self.radio.state = self.radio.amstate
34 
35 
36 class Radio(object):
37     """A radio.     It has a scan button, and an AM/FM toggle switch."""
38 
39     def __init__(self):
40         """We have an AM state and an FM state"""
41         self.amstate = AmState(self)
42         self.fmstate = FmState(self)
43         self.state = self.amstate
44 
45     def toggle_amfm(self):
46         self.state.toggle_amfm()
47 
48     def scan(self):
49         self.state.scan()
50 
51 
52 # Test our radio out
53 if __name__ == '__main__':
54     radio = Radio()
55     actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2
56     actions = actions * 2
57 
58     for action in actions:
59         action()
View Code

共享模式

 1 class Borg:
 2     __shared_state = {}
 3 
 4     def __init__(self):
 5         self.__dict__ = self.__shared_state
 6 
 7     def __str__(self):
 8         return self.state
 9 
10 
11 class YourBorg(Borg):
12     pass
13 
14 if __name__ == '__main__':
15     rm1 = Borg()
16     rm2 = Borg()
17 
18     rm1.state = 'Idle'
19     rm2.state = 'Running'
20 
21     print('rm1:', rm1)
22     print('rm2:', rm2)
23 
24     rm2.state = 'Zombie'
25 
26     print('rm1:', rm1)
27     print('rm2:', rm2)
28 
29     print('rm1 id:', id(rm1))
30     print('rm2 id:', id(rm2))
31 
32     rm3 = YourBorg()
33 
34     print('rm1:', rm1)
35     print('rm2:', rm2)
36     print('rm3:', rm3)
View Code

 

 

 


创建型模式:

设计模式-创建型模式
工厂模式 、抽象工厂模式设计模式
建造者模式设计模式
原型模式设计模式
python享元模式
python单例模式

设计模式,python延迟计算缓存模式
python对象池模式

 

结构型模式:
python 桥接模式
适配器模式

设计模式-结构型模式,python组合模式
python 桥接模式
适配器模式
装饰器模式:http://www.cnblogs.com/ydf0509/p/8525692.html
外观模式:http://www.cnblogs.com/ydf0509/p/8525853.html
mvc模式:http://www.cnblogs.com/ydf0509/p/8525949.html
代理模式:http://www.cnblogs.com/ydf0509/p/8525970.html

行为型模式:
责任链模式:http://www.cnblogs.com/ydf0509/p/8525991.html
命令模式:http://www.cnblogs.com/ydf0509/p/8526012.html
解释器模式:http://www.cnblogs.com/ydf0509/p/8526064.html
观察者模式:http://www.cnblogs.com/ydf0509/p/8526100.html
状态模式:http://www.cnblogs.com/ydf0509/p/8527468.html
策略模式:http://www.cnblogs.com/ydf0509/p/8527515.html

模板模式:http://www.cnblogs.com/ydf0509/p/8527685.html
设计模式-行为型模式,
python 中介者模式设计模式-行为型模式,
python备忘录模式设计模式-行为型模式,
python访问者模式python 迭代器模式
业务代表模式
组合实体模式

python设计模式之猴子补丁模式
python独有模式

为保证对模式没有误解和误判,代码例子是用的从精通python 16种设计模式那本书中的,有的用的网上的。

一个在线的 http://www.pythontip.com/pythonPatterns/
github的 https://github.com/faif/python-patterns
菜鸟教程的 http://www.runoob.com/design-pattern/design-pattern-tutorial.html

posted @ 2019-04-12 17:11  逐梦客!  阅读(732)  评论(0)    收藏  举报