python——设计模式

Posted YC的技术笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python——设计模式相关的知识,希望对你有一定的参考价值。

 

设计模式是什么?

设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码。反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言。一个好的设计模式应该能够用大部分编程语言实现(如果做不到全部的话,具体取决于语言特性)。最为重要的是,设计模式也是一把双刃剑,如果设计模式被用在不恰当的情形下将会造成灾难,进而带来无穷的麻烦。然而如果设计模式在正确的时间被用在正确地地方,它将是你的救星。

起初,你会认为“模式”就是为了解决一类特定问题而特别想出来的明智之举。说的没错,看起来的确是通过很多人一起工作,从不同的角度看待问题进而形成的一个最通用、最灵活的解决方案。也许这些问题你曾经见过或是曾经解决过,但是你的解决方案很可能没有模式这么完备。

虽然被称为“设计模式”,但是它们同“设计“领域并非紧密联系。设计模式同传统意义上的分析、设计与实现不同,事实上设计模式将一个完整的理念根植于程序中,所以它可能出现在分析阶段或是更高层的设计阶段。很有趣的是因为设计模式的具体体现是程序代码,因此可能会让你认为它不会在具体实现阶段之前出现(事实上在进入具体实现阶段之前你都没有意识到正在使用具体的设计模式)。

可以通过程序设计的基本概念来理解模式:增加一个抽象层。抽象一个事物就是隔离任何具体细节,这么做的目的是为了将那些不变的核心部分从其他细节中分离出来。当你发现你程序中的某些部分经常因为某些原因改动,而你不想让这些改动的部分引发其他部分的改动,这时候你就需要思考那些不会变动的设计方法了。这么做不仅会使代码可维护性更高,而且会让代码更易于理解,从而降低开发成本。

这里列举了三种最基本的设计模式:

  1. 创建模式,提供实例化的方法,为适合的状况提供相应的对象创建方法。
  2. 结构化模式,通常用来处理实体之间的关系,使得这些实体能够更好地协同工作。
  3. 行为模式,用于在不同的实体建进行通信,为实体之间的通信提供更容易,更灵活的通信方法。
创建型

1. Factory Method(工厂方法)

2. Abstract Factory(抽象工厂)

3. Builder(建造者)

4. Prototype(原型)

5. Singleton(单例)

结构型

6. Adapter Class/Object(适配器)

7. Bridge(桥接)

8. Composite(组合)

9. Decorator(装饰)

10. Facade(外观)

11. Flyweight(享元)

12. Proxy(代理)

行为型

13. Interpreter(解释器)

14. Template Method(模板方法)

15. Chain of Responsibility(责任链)

16. Command(命令)

17. Iterator(迭代器)

18. Mediator(中介者)

19. Memento(备忘录)

20. Observer(观察者)

21. State(状态)

22. Strategy(策略)

23. Visitor(访问者)
View Code

 

创建型

1.Factory Method(工厂方法)

意图:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使个类的实例化延迟到其子类。

适用性:

当一个类不知道它所必须创建的对象的类的时候。

当一个类希望由它的子类来指定它所创建的对象的时候。

当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

实现:

 1 !/usr/bin/python
 2 #coding:utf8
 3 \'\'\'
 4 Factory Method
 5 \'\'\'
 6  
 7 class ChinaGetter:
 8     """A simple localizer a la gettext"""
 9     def __init__(self):
10         self.trans = dict(dog=u"小狗", cat=u"小猫")
11  
12     def get(self, msgid):
13         """We\'ll punt if we don\'t have a translation"""
14         try:
15             return self.trans[msgid]
16         except KeyError:
17             return str(msgid)
18  
19  
20 class EnglishGetter:
21     """Simply echoes the msg ids"""
22     def get(self, msgid):
23         return str(msgid)
24  
25  
26 def get_localizer(language="English"):
27     """The factory method"""
28     languages = dict(English=EnglishGetter, China=ChinaGetter)
29     return languages[language]()
30  
31 # Create our localizers
32 e, g = get_localizer("English"), get_localizer("China")
33 # Localize some text
34 for msgid in "dog parrot cat bear".split():
35     print(e.get(msgid), g.get(msgid))
View Code

 

2. Abstract Factory(抽象工厂)

意图:

 

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 
适用性:

 一个系统要独立于它的产品的创建、组合和表示时。

 一个系统要由多个产品系列中的一个来配置时。

 当你要强调一系列相关的产品对象的设计以便进行联合使用时。

 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

实现:

 1 #!/usr/bin/python
 2 #coding:utf8
 3 \'\'\'
 4 Abstract Factory
 5 \'\'\'
 6  
 7 import random
 8  
 9 class PetShop:
10     """A pet shop"""
11  
12     def __init__(self, animal_factory=None):
13         """pet_factory is our abstract factory.
14         We can set it at will."""
15  
16         self.pet_factory = animal_factory
17  
18     def show_pet(self):
19         """Creates and shows a pet using the
20         abstract factory"""
21  
22         pet = self.pet_factory.get_pet()
23         print("This is a lovely", str(pet))
24         print("It says", pet.speak())
25         print("It eats", self.pet_factory.get_food())
26  
27  
28 # Stuff that our factory makes
29  
30 class Dog:
31     def speak(self):
32         return "woof"
33  
34     def __str__(self):
35         return "Dog"
36  
37  
38 class Cat:
39     def speak(self):
40         return "meow"
41  
42     def __str__(self):
43         return "Cat"
44  
45  
46 # Factory classes
47  
48 class DogFactory:
49     def get_pet(self):
50         return Dog()
51  
52     def get_food(self):
53         return "dog food"
54  
55  
56 class CatFactory:
57     def get_pet(self):
58         return Cat()
59  
60     def get_food(self):
61         return "cat food"
62  
63  
64 # Create the proper family
65 def get_factory():
66     """Let\'s be dynamic!"""
67     return random.choice([DogFactory, CatFactory])()
68  
69  
70 # Show pets with various factories
71 if __name__ == "__main__":
72     shop = PetShop()
73     for i in range(3):
74         shop.pet_factory = get_factory()
75         shop.show_pet()
76         print("=" * 20)
View Code

 

3. Builder(建造者)

意图:

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

适用性:

当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。

当构造过程必须允许被构造的对象有不同的表示时。

 

 1 #!/usr/bin/python
 2 #coding:utf8
 3  
 4 """
 5     Builder
 6 """
 7  
 8 # Director
 9 class Director(object):
10     def __init__(self):
11         self.builder = None
12  
13     def construct_building(self):
14         self.builder.new_building()
15         self.builder.build_floor()
16         self.builder.build_size()
17  
18     def get_building(self):
19         return self.builder.building
20  
21  
22 # Abstract Builder
23 class Builder(object):
24     def __init__(self):
25         self.building = None
26  
27     def new_building(self):
28         self.building = Building()
29  
30  
31 # Concrete Builder
32 class BuilderHouse(Builder):
33     def build_floor(self):
34         self.building.floor = \'One\'
35  
36     def build_size(self):
37         self.building.size = \'Big\'
38  
39  
40 class BuilderFlat(Builder):
41     def build_floor(self):
42         self.building.floor = \'More than One\'
43  
44     def build_size(self):
45         self.building.size = \'Small\'
46  
47  
48 # Product
49 class Building(object):
50     def __init__(self):
51         self.floor = None
52         self.size = None
53  
54     def __repr__(self):
55         return \'Floor: %s | Size: %s\' % (self.floor, self.size)
56  
57  
58 # Client
59 if __name__ == "__main__":
60     director = Director()
61     director.builder = BuilderHouse()
62     director.construct_building()
63     building = director.get_building()
64     print(building)
65     director.builder = BuilderFlat()
66     director.construct_building()
67     building = director.get_building()
68     print(building)
View Code

 

 

 

4. Prototype(原型)

意图:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

适用性:

当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者为了避免创建一个与产品类层次平行的工厂类层次时;或者当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

 

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

 

5. Singleton(单例)

意图:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

适用性:

当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

 

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/python
#coding:utf8
\'\'\'
Singleton
\'\'\'
 
class Singleton(object):
    \'\'\'\'\' A python style singleton \'\'\'
 
    def __new__(cls*args, **kw):
        if not hasattr(cls\'_instance\'):
            org = super(Singleton, cls)
            cls._instance = org.__new__(cls*args, **kw)
        return cls._instance
 
 
if __name__ == \'__main__\':
    class SingleSpam(Singleton):
        def __init__(self, s):
            self.s = s
 
        def __str__(self):
            return self.s
 
 
    s1 = SingleSpam(\'spam\')
    print id(s1), s1
    s2 = SingleSpam(\'spa\')
    print id(s2), s2
    print id(s1), s1

  

结构型

6. Adapter Class/Object(适配器)

意图:

 将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 

适用性:

 你想使用一个已经存在的类,而它的接口不符合你的需求。

你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。

(仅适用于对象Adapter )你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

(c)2006-2024 SYSTEM All Rights Reserved IT常识