├── 00_designpattern_theory └── design_pattern_principle.py ├── 01_creational_pattern ├── 01_singleton.py ├── 02_simple_factory.py ├── 03_factory_method.py ├── 04_abstract_factory.py ├── 05_builder.py └── 06_prototype.py ├── 02_structural_pattern ├── 01_adapter.py ├── 02_bridge.py ├── 03_decorator.py ├── 04_facade.py ├── 05_flyweight.py ├── 06_proxy.py └── 07_composite.py ├── 03_behavioral_pattern ├── 01_responsibility_chain.py ├── 02_command.py ├── 03_mediator.py ├── 04_observer.py ├── 05_state.py ├── 06_strategy.py ├── 07_interpreter.py ├── 08_iterator.py ├── 09_memento.py ├── 10_template_method.py └── 11_visitor.py └── README.md /00_designpattern_theory/design_pattern_principle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | 5 | """ 6 | 开闭原则 (Open Closed Principle,OCP) 7 | 一个软件实体(如类、模块、函数)应该:对扩展开放,对修改关闭。 8 | 模块应尽量在不修改原代码的情况下进行扩展。 9 | 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。 10 | 11 | 12 | 里氏代换原则 (Liskov Substitution Principle,LSP) 13 | 派生类(子类)对象能够替换其基类(父类)对象被调用。 14 | 任何基类可以出现的地方,子类一定可以出现。 15 | 该原则是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。 16 | 里氏代换原则是对“开闭”原则的补充。 17 | 实现“开闭”原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。 18 | 19 | 20 | 依赖倒转原则 (Dependency Inversion Principle,DIP) 21 | 程序要依赖于抽象接口,不要依赖于具体实现。 22 | 简单的说就是,要求对抽象进行编程,不要对实现进行编程, 23 | 这样就降低了客户与实现模块间的耦合。 24 | 25 | 26 | 接口隔离原则 (Interface Segregation Principle,ISP) 27 | 客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。 28 | 尽量使用多个隔离的接口,而不是使用单个接口。 29 | 目的是降低类之间的耦合度。 30 | 31 | 32 | 合成/聚合复用原则 (Composite/Aggregate Reuse Principle,CARP) 33 | (别名: 合成复用原则) 34 | 在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分; 35 | 新对象通过委派调用已有对象的方法达到复用其已有功能的目的。 36 | 它的设计原则是:要尽量使用合成/聚合,尽量不要使用继承。 37 | 38 | 39 | 最小知识原则 (Principle of Least Knowledge,PLK) 40 | (别名: 迪米特法则 Law of Demeter) 41 | 一个软件实体应当尽可能少的与其他实体发生相互作用,使得系统功能模块相对独立。 42 | 一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。 43 | 由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。 44 | 这样,当一个模块修改时,就会尽量少的影响其他的模块,扩展会相对容易, 45 | 这是对软件实体之间通信的限制,它要求限制软件实体之间通信的宽度和深度。 46 | 应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类, 47 | 这些类之所以存在完全是为了传递类之间的相互调用关系,这在一定程度上增加了系统的复杂度。 48 | """ 49 | 50 | -------------------------------------------------------------------------------- /01_creational_pattern/01_singleton.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | 5 | """ 6 | 单例模式(Singleton Pattern) 7 | 单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。 8 | 9 | 包含角色 10 | [Singleton][单例] 11 | 12 | 单例模式的要点有三个 13 | 一是某个类只能有一个实例; 14 | 二是它必须自行创建这个实例; 15 | 三是它必须自行向整个系统提供这个实例。 16 | 17 | 单例模式只包含一个单例角色,在单例类的内部实现只生成一个实例,同时它提供一个静态的工厂方法,让客户可以使用它的唯一实例; 18 | 为了防止在外部对其实例化,将其构造函数设计为私有。 19 | 20 | 单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。 21 | 单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。 22 | 除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法。 23 | 该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。 24 | 25 | 优点 26 | 提供了对唯一实例的受控访问并可以节约系统资源; 27 | 28 | 缺点 29 | 因为缺少抽象层而难以扩展,且单例类职责过重; 30 | 31 | 适用情况 32 | 系统只需要一个实例对象; 33 | 客户调用类的单个实例只允许使用一个公共访问点。 34 | 35 | 单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。 36 | """ 37 | """ 38 | 单例模式实现方法 39 | """ 40 | print '----------------------------------------------------------------------------------------------------' 41 | """ 42 | [方法1][共享实例] 43 | 实现__new__方法,并将一个类的实例绑定到类变量_instance上, 44 | 如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回; 45 | 如果cls._instance非None说明该类已经被实例化过,直接返回cls._instance; 46 | """ 47 | """ 48 | 在 Java 中, 49 | 静态变量(在Python中叫类属性)和实例变量(在Python中叫数据属性)两者都是紧跟在类定义之后定义的(一个有static关键字,一个没有)。 50 | 在 Python 中, 51 | 只有类属性可以紧跟在类定义之后定义,数据属性定义在__init__方法中。 52 | """ 53 | 54 | class Singleton(object): 55 | def __new__(cls, *args, **kwargs): 56 | if not hasattr(cls, '_instance'): 57 | cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) 58 | return cls._instance # class attribute !!!!! 59 | 60 | class MyClass(Singleton): 61 | pass 62 | 63 | a = MyClass() 64 | b = MyClass() 65 | 66 | print a, id(a) 67 | print b, id(b) 68 | # <__main__.MyClass object at 0x102113a50> 4329650768 69 | # <__main__.MyClass object at 0x102113a50> 4329650768 70 | print '----------------------------------------------------------------------------------------------------' 71 | """ 72 | [方法2][共享属性] 73 | 创建实例时,将所有实例的__dict__指向同一个字典(dict),使得它们具有相同的属性和方法。 74 | """ 75 | """ 76 | 所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)。 77 | 同一个类的所有实例天然拥有相同的行为(方法),只需要保证同一个类的所有实例具有相同的状态(属性)即可。 78 | 对任何实例的名字属性的设置,无论是在__init__中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。 79 | """ 80 | """ 81 | object.__dict__ 82 | A dictionary or other mapping object used to store an object’s (writable) attributes. 83 | 注意区分: 84 | class.__dict__ 85 | instance.__dict__ 86 | """ 87 | 88 | class Bravo(object): 89 | _shared_state = {} 90 | 91 | def __new__(cls, *args, **kwargs): 92 | obj = super(Bravo, cls).__new__(cls, *args, **kwargs) 93 | obj.__dict__ = cls._shared_state # instance.__dict__ = class._shared_state 94 | return obj 95 | 96 | class MyClass2(Bravo): 97 | x = 1 98 | pass 99 | 100 | a = MyClass2() 101 | b = MyClass2() 102 | 103 | a.x = 9 104 | 105 | print a, id(a) 106 | print b, id(b) 107 | # <__main__.MyClass2 object at 0x10defec50> 4528794704 108 | # <__main__.MyClass2 object at 0x10defecd0> 4528794832 109 | print a.x, id(a.x), a.__dict__, id(a.__dict__), id(Bravo._shared_state) 110 | print b.x, id(b.x), b.__dict__, id(b.__dict__), id(Bravo._shared_state) 111 | # 9 140325309983816 {'x': 9} 140325311114016 140325311114016 112 | # 9 140325309983816 {'x': 9} 140325311114016 140325311114016 113 | print Bravo._shared_state, id(Bravo._shared_state) 114 | # {'x': 9} 140325311114016 115 | print '----------------------------------------------------------------------------------------------------' 116 | """ 117 | [方法3][装饰器] 118 | 其实是方法1的升级(高级)版, 119 | 使用装饰器(decorator),这是更加 pythonic、更加 elegant 的方法。 120 | """ 121 | 122 | def singleton(cls, *args, **kwargs): 123 | instances = {} 124 | def _singleton(): 125 | if cls not in instances: 126 | instances[cls] = cls(*args, **kwargs) 127 | return instances[cls] 128 | return _singleton 129 | 130 | @singleton 131 | class MyClass3(object): 132 | ca = 1 133 | def __init__(self, x=0): 134 | self.x = x 135 | 136 | a = MyClass3() 137 | b = MyClass3() 138 | 139 | print a, id(a) 140 | print b, id(b) 141 | a.ca = 9 142 | print a.ca, id(a.ca) 143 | print b.ca, id(b.ca) 144 | 145 | # 使用 @singleton 修饰前 146 | # <__main__.MyClass3 object at 0x10d458e10> 4517629456 147 | # <__main__.MyClass3 object at 0x10d458d90> 4517629328 148 | # 9 140491095055720 149 | # 1 140491095055912 150 | 151 | # 使用 @singleton 修饰后 152 | # <__main__.MyClass3 object at 0x106dffe10> 4410310160 153 | # <__main__.MyClass3 object at 0x106dffe10> 4410310160 154 | # 9 140683822311880 155 | # 9 140683822311880 156 | print '----------------------------------------------------------------------------------------------------' 157 | """ 158 | [方法4][__metaclass__] 159 | 本质上也是方法1的升级(高级)版, 160 | 使用 __metaclass__(元类)的高级用法 161 | """ 162 | """ 163 | __metaclass__ 164 | This variable can be any callable accepting arguments for name, bases, and dict. 165 | Upon class creation, the callable is used instead of the built-in type(). 166 | 167 | The appropriate metaclass is determined by the following precedence rules: 168 | If dict['__metaclass__'] exists, it is used. 169 | Otherwise, if there is at least one base class, its metaclass is used 170 | (this looks for a __class__ attribute first and if not found, uses its type). 171 | Otherwise, if a global variable named __metaclass__ exists, it is used. 172 | Otherwise, the old-style, classic metaclass (types.ClassType) is used. 173 | 174 | object.__call__(self[, args...]) 175 | Called when the instance is “called” as a function; 176 | if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...). 177 | 178 | class type(name, bases, dict) 179 | With three arguments, return a new type object. 180 | This is essentially a dynamic form of the class statement. 181 | The name string is the class name and becomes the __name__ attribute; 182 | the bases tuple itemizes the base classes and becomes the __bases__ attribute; 183 | the dict dictionary is the namespace containing definitions for class body and becomes the __dict__ attribute. 184 | """ 185 | class Singleton_meta(type): 186 | def __init__(cls, name, bases, dict): 187 | super(Singleton_meta, cls).__init__(name, bases, dict) 188 | cls._instance = None 189 | def __call__(cls, *args, **kwargs): 190 | if cls._instance is None: 191 | cls._instance = super(Singleton_meta, cls).__call__(*args, **kwargs) 192 | return cls._instance 193 | 194 | class MyClass4(object): 195 | __metaclass__ = Singleton_meta 196 | 197 | a = MyClass4() 198 | b = MyClass4() 199 | 200 | print a, id(a) 201 | print b, id(b) 202 | # <__main__.MyClass5 object at 0x10b883150> 4488442192 203 | # <__main__.MyClass5 object at 0x10b883150> 4488442192 204 | 205 | a.x = 9 206 | print a.x, id(a.x) 207 | print b.x, id(b.x) 208 | # 9 140466549987320 209 | # 9 140466549987320 210 | print '----------------------------------------------------------------------------------------------------' 211 | """ 212 | [方法5][import] 213 | 作为python的模块是天然的单例模式 214 | """ 215 | """ 216 | # 在其他模块文件(mysingleton.py)中定义: 217 | 218 | class My_Singleton(object): 219 | def foo(self): 220 | print id(self) 221 | 222 | my_singleton = My_Singleton() 223 | """ 224 | 225 | # 在当前模块文件中使用 226 | from mysingleton import my_singleton 227 | my_singleton.foo() 228 | # 4473651024 229 | from mysingleton import my_singleton 230 | my_singleton.foo() 231 | # 4473651024 232 | print '----------------------------------------------------------------------------------------------------' 233 | -------------------------------------------------------------------------------- /01_creational_pattern/02_simple_factory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 简单工厂模式(Simple Factory Pattern) 6 | 在简单工厂模式中,可以根据参数的不同返回不同类的实例。 7 | 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。 8 | 9 | 包含三个角色 10 | [AbstractProduct][抽象产品] 11 | 是所创建的所有对象的父类,负责描述所有实例所共有的公共接口; 12 | [ConcreteProduct][具体产品] 13 | 是创建目标,所有创建的对象都充当这个角色的某个具体类的实例; 14 | [Factory][工厂] 15 | 负责实现创建所有实例的内部逻辑; 16 | 17 | 优点 18 | 实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责; 19 | 20 | 缺点 21 | 工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂; 22 | 23 | 适用情况 24 | 工厂类负责创建的对象比较少; 25 | 客户端只知道传入工厂类的参数,对于如何创建对象不关心。 26 | 27 | 简单工厂模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。 28 | """ 29 | 30 | class Product_abstract(object): 31 | """ 32 | 抽象产品 33 | """ 34 | def use(self): 35 | pass 36 | 37 | class Product_concrete_1(Product_abstract): 38 | """ 39 | 具体产品 1 40 | """ 41 | def use(self): 42 | print 'using:', self.__class__.__name__ 43 | 44 | class Product_concrete_2(Product_abstract): 45 | """ 46 | 具体产品 2 47 | """ 48 | def use(self): 49 | print 'using:', self.__class__.__name__ 50 | 51 | class Factory(object): 52 | """ 53 | 工厂 54 | """ 55 | def create_product(self, type): 56 | if type == 1: 57 | return Product_concrete_1() 58 | elif type == 2: 59 | return Product_concrete_2() 60 | else: 61 | return None 62 | 63 | 64 | factory = Factory() 65 | 66 | operation = factory.create_product(1) 67 | operation.use() 68 | # using: Product_concrete_1 69 | 70 | operation = factory.create_product(2) 71 | operation.use() 72 | # using: Product_concrete_2 73 | -------------------------------------------------------------------------------- /01_creational_pattern/03_factory_method.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 工厂方法模式(Factory Method Pattern) 6 | 在工厂方法模式中, 7 | 工厂父类负责定义创建产品对象的公共接口, 8 | 工厂子类则负责生成具体的产品对象, 9 | 这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。 10 | 11 | 包含四个角色 12 | [AbstractProduct][抽象产品] 13 | 是定义产品的接口,是工厂方法模式所创建对象的超类型,即产品对象的共同父类或接口; 14 | [ConcreteProduct][具体产品] 15 | 实现了抽象产品接口,某种类型的具体产品由专门的具体工厂创建,它们之间往往一一对应; 16 | [AbstractFactory][抽象工厂] 17 | 中声明了工厂方法,用于返回一个产品,它是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口; 18 | [ConcreteFactory][具体工厂] 19 | 是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户调用,返回一个具体产品类的实例; 20 | 21 | 工厂方法模式是简单工厂模式的进一步抽象和推广。 22 | 由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。 23 | 在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。 24 | 这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节, 25 | 这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。 26 | 27 | 优点 28 | 增加新的产品类时无须修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性; 29 | 30 | 缺点 31 | 增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性; 32 | 33 | 适用情况 34 | 一个类不知道它所需要的对象的类; 35 | 一个类通过其子类来指定创建哪个对象; 36 | 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。 37 | 38 | 工厂方法模式又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。 39 | """ 40 | 41 | class Product_abstract(object): 42 | """ 43 | 抽象产品 44 | """ 45 | def use(self): 46 | pass 47 | 48 | class Product_concrete_1(Product_abstract): 49 | """ 50 | 具体产品 1 51 | """ 52 | def use(self): 53 | print 'using:', self.__class__.__name__ 54 | 55 | class Product_concrete_2(Product_abstract): 56 | """ 57 | 具体产品 2 58 | """ 59 | def use(self): 60 | print 'using:', self.__class__.__name__ 61 | 62 | class Factory_abstract(object): 63 | """ 64 | 抽象工厂 65 | """ 66 | def create_product(self): 67 | return Product_abstract() 68 | 69 | class Factory_concrete_1(Factory_abstract): 70 | """ 71 | 具体工厂 1 72 | """ 73 | def create_product(self): 74 | return Product_concrete_1() 75 | 76 | class Factory_concrete_2(Factory_abstract): 77 | """ 78 | 具体工厂 2 79 | """ 80 | def create_product(self): 81 | return Product_concrete_2() 82 | 83 | 84 | factory_int = Factory_concrete_1() 85 | product_int = factory_int.create_product() 86 | product_int.use() 87 | # using: Product_concrete_1 88 | 89 | factory_str = Factory_concrete_2() 90 | product_str = factory_str.create_product() 91 | product_str.use() 92 | # using: Product_concrete_2 93 | -------------------------------------------------------------------------------- /01_creational_pattern/04_abstract_factory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | 5 | """ 6 | 抽象工厂模式(Abstract Factory Pattern) 7 | 提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。 8 | 9 | 包含四个角色 10 | [AbstractProduct][抽象产品] 11 | 为每种产品声明接口,在抽象产品中定义了产品的抽象业务方法; 12 | [ConcreteProduct][具体产品] 13 | 定义具体工厂生产的具体产品对象,实现抽象产品接口中定义的业务方法; 14 | [AbstractFactory][抽象工厂] 15 | 用于声明生成抽象产品的方法; 16 | [ConcreteFactory][具体工厂] 17 | 实现了抽象工厂声明的生成抽象产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中; 18 | 19 | 抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。 20 | 抽象工厂模式与工厂方法模式最大的区别在于, 21 | 工厂方法模式针对的是一个产品等级结构, 22 | 抽象工厂模式则需要面对多个产品等级结构。 23 | 24 | 优点 25 | 隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象, 26 | 增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便; 27 | 28 | 缺点 29 | 增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开闭原则”的支持呈现倾斜性; 30 | 31 | 适用情况 32 | 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节; 33 | 系统中有多于一个的产品族,而每次只使用其中某一产品族; 34 | 属于同一个产品族的产品将在一起使用; 35 | 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。 36 | 37 | 抽象工厂模式又称为Kit模式,属于对象创建型模式。 38 | """ 39 | 40 | class Product_abstract_A(object): 41 | """ 42 | 抽象产品 A 43 | """ 44 | def use(self): 45 | pass 46 | 47 | class Product_concrete_A_1(Product_abstract_A): 48 | """ 49 | 具体产品 A 1 50 | """ 51 | def use(self): 52 | print 'using:', self.__class__.__name__ 53 | 54 | class Product_concrete_A_2(Product_abstract_A): 55 | """ 56 | 具体产品 A 2 57 | """ 58 | def use(self): 59 | print 'using:', self.__class__.__name__ 60 | 61 | 62 | class Product_abstract_B(object): 63 | """ 64 | 抽象产品 B 65 | """ 66 | def use(self): 67 | pass 68 | 69 | class Product_concrete_B_1(Product_abstract_B): 70 | """ 71 | 具体产品 B 1 72 | """ 73 | def use(self): 74 | print 'using:', self.__class__.__name__ 75 | 76 | class Product_concrete_B_2(Product_abstract_B): 77 | """ 78 | 具体产品 B 2 79 | """ 80 | def use(self): 81 | print 'using:', self.__class__.__name__ 82 | 83 | 84 | class Factory_abstract(object): 85 | """ 86 | 抽象工厂 87 | """ 88 | def create_product_A(self): 89 | return Product_abstract_A() 90 | def create_product_B(self): 91 | return Product_abstract_B() 92 | 93 | class Factory_concrete_1(Factory_abstract): 94 | """ 95 | 具体工厂 1 96 | """ 97 | def create_product_A(self): 98 | return Product_concrete_A_1() 99 | def create_product_B(self): 100 | return Product_concrete_B_1() 101 | 102 | class Factory_concrete_2(Factory_abstract): 103 | """ 104 | 具体工厂 2 105 | """ 106 | def create_product_A(self): 107 | return Product_concrete_A_2() 108 | def create_product_B(self): 109 | return Product_concrete_B_2() 110 | 111 | 112 | factory_1 = Factory_concrete_1() 113 | product_A_int = factory_1.create_product_A() 114 | product_A_int.use() 115 | # using: Product_concrete_A_1 116 | product_B_int = factory_1.create_product_B() 117 | product_B_int.use() 118 | # using: Product_concrete_B_1 119 | 120 | factory_2 = Factory_concrete_2() 121 | product_A_str = factory_2.create_product_A() 122 | product_A_str.use() 123 | # using: Product_concrete_A_2 124 | product_B_str = factory_2.create_product_B() 125 | product_B_str.use() 126 | # using: Product_concrete_B_2 127 | -------------------------------------------------------------------------------- /01_creational_pattern/05_builder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 建造者模式(Builder Pattern) 6 | 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 7 | 建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。 8 | 9 | 包含四个角色 10 | [Product][产品] 11 | 是被构建的复杂对象,包含多个组成部件; 12 | [AbstractBuilder][抽象建造者] 13 | 为创建一个产品对象的各个部件指定抽象接口; 14 | [ConcreteBuilder][具体建造者] 15 | 实现了抽象建造者接口,实现各个部件的构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象; 16 | [Director][指挥者] 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 | class Product(object): 43 | """ 44 | 产品 45 | """ 46 | def __init__(self): 47 | self.part_a = None 48 | self.part_b = None 49 | def __str__(self): 50 | return '[product:%s]=[part_a:%s]+[part_b:%s]' % (self.__class__.__name__, self.part_a, self.part_b) 51 | 52 | class Builder_abstract(object): 53 | """ 54 | 抽象建造者 55 | """ 56 | def __init__(self): 57 | self.product = None 58 | def new_product(self): 59 | self.product = Product() 60 | def build_partA(self): 61 | pass 62 | def build_partB(self): 63 | pass 64 | 65 | class Builder_concrete_1(Builder_abstract): 66 | """ 67 | 具体建造者 1 68 | """ 69 | def build_partA(self): 70 | self.product.part_a = 'big Part_A' 71 | def build_partB(self): 72 | self.product.part_b = 'big Part_B' 73 | 74 | class Builder_concrete_2(Builder_abstract): 75 | """ 76 | 具体建造者 2 77 | """ 78 | def build_partA(self): 79 | self.product.part_a = 'small Part_A' 80 | def build_partB(self): 81 | self.product.part_b = 'small Part_B' 82 | 83 | class Director(object): 84 | """ 85 | 指挥者 86 | """ 87 | def __init__(self, builder): 88 | self.builder = builder 89 | def build_parts(self): 90 | self.builder.new_product() 91 | self.builder.build_partA() 92 | self.builder.build_partB() 93 | def get_product(self): 94 | return self.builder.product 95 | 96 | 97 | builder_1 = Builder_concrete_1() 98 | director_1 = Director(builder_1) 99 | director_1.build_parts() 100 | product_1 = director_1.get_product() 101 | print product_1 102 | # [product:Product]=[part_a:big Part_A]+[part_b:big Part_B] 103 | 104 | builder_2 = Builder_concrete_2() 105 | director_2 = Director(builder_2) 106 | director_2.build_parts() 107 | product_2 = director_2.get_product() 108 | print product_2 109 | # [product:Product]=[part_a:small Part_A]+[part_b:small Part_B] 110 | -------------------------------------------------------------------------------- /01_creational_pattern/06_prototype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 原型模式(Prototype Pattern) 6 | 用原型实例指定创建对象的种类,并且通过拷贝(复制)这些原型创建新的对象。 7 | 8 | 包含二个角色 9 | [AbstractPrototype][抽象原型类] 10 | 声明克隆自身的接口。 11 | [ConcretePrototype][具体原型类] 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 | import copy 37 | 38 | class Prototype_abstract(object): 39 | """ 40 | 抽象原型类 41 | """ 42 | def clone(self): 43 | pass 44 | 45 | class Prototype_concrete(Prototype_abstract): 46 | """ 47 | 具体原型类 48 | """ 49 | def clone(self, **kwargs): 50 | new_object = copy.deepcopy(self) 51 | new_object.__dict__.update(**kwargs) 52 | return new_object 53 | 54 | 55 | # 让一个原型克隆自身,从而获得一个新的对象: 56 | prototype_0 = Prototype_concrete() 57 | prototype_a = prototype_0.clone(a='A') 58 | prototype_b = prototype_a.clone(b='B') 59 | prototype_c = prototype_b.clone(c='C') 60 | 61 | print id(prototype_0), prototype_0.__dict__ 62 | print id(prototype_a), prototype_a.__dict__ 63 | print id(prototype_b), prototype_b.__dict__ 64 | print id(prototype_c), prototype_c.__dict__ 65 | # 4559790800 {} 66 | # 4559790992 {'a': 'A'} 67 | # 4559791056 {'a': 'A', 'b': 'B'} 68 | # 4559791120 {'a': 'A', 'c': 'C', 'b': 'B'} 69 | -------------------------------------------------------------------------------- /02_structural_pattern/01_adapter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 适配器模式(Adapter Pattern) 6 | 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。 7 | 适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。 8 | 9 | 包含三个角色 10 | [Target][目标抽象类] 11 | 定义客户要用的特定领域的接口; 12 | [Adaptee][适配者类] 13 | 是被适配的角色,它定义了一个已经存在的接口,这个接口需要适配; 14 | [Adapter][适配器类] 15 | 可以调用另一个接口,作为一个转换器,对适配者和抽象目标类进行适配,它是适配器模式的核心; 16 | 17 | 在类适配器模式中,适配器类实现了目标抽象类接口并继承了适配者类,并在目标抽象类的实现方法中调用所继承的适配者类的方法; 18 | 在对象适配器模式中,适配器类继承了目标抽象类并定义了一个适配者类的对象实例,在所继承的目标抽象类方法中调用适配者类的相应业务方法。 19 | 20 | 优点 21 | 将目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常好,更换适配器或者增加新的适配器都非常方便,符合“开闭原则”; 22 | 23 | 缺点 24 | 类适配器模式的缺点是适配器类在很多编程语言中不能同时适配多个适配者类; 25 | 对象适配器模式的缺点是很难置换适配者类的方法; 26 | 27 | 适用情况 28 | 系统需要使用现有的类,而这些类的接口不符合系统的需要; 29 | 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作。 30 | """ 31 | 32 | class Cat(object): 33 | """ 34 | 适配者类 35 | """ 36 | def __init__(self): 37 | self.name = self.__class__.__name__ 38 | def meow(self): 39 | return 'meow ~' 40 | 41 | class Dog(object): 42 | """ 43 | 适配者类 44 | """ 45 | def __init__(self): 46 | self.name = self.__class__.__name__ 47 | def bark(self): 48 | return 'woof !' 49 | 50 | class Human(object): 51 | """ 52 | 适配者类 53 | """ 54 | def __init__(self): 55 | self.name = self.__class__.__name__ 56 | def speak(self): 57 | return 'hello ?' 58 | 59 | class Target(object): 60 | """ 61 | 目标抽象类 62 | """ 63 | def make_noise(self): 64 | return '......' 65 | 66 | class Adapter(Target): 67 | """ 68 | 适配器类 69 | """ 70 | def __init__(self, adaptee): 71 | self.adaptee = adaptee 72 | """ 73 | object.__getattr__(self, name) 74 | Called when an attribute lookup has not found the attribute in the usual places 75 | (i.e. it is not an instance attribute nor is it found in the class tree for self). 76 | name is the attribute name. 77 | This method should return the (computed) attribute value or raise an AttributeError exception. 78 | """ 79 | def __getattr__(self, attr): 80 | return getattr(self.adaptee, attr) 81 | def make_noise(self): 82 | if isinstance(self.adaptee, Cat): 83 | return self.adaptee.meow() 84 | elif isinstance(self.adaptee, Dog): 85 | return self.adaptee.bark() 86 | elif isinstance(self.adaptee, Human): 87 | return self.adaptee.speak() 88 | 89 | 90 | cat = Cat() 91 | dog = Dog() 92 | human = Human() 93 | animals = [Adapter(cat), Adapter(dog), Adapter(human)] 94 | # 针对目标抽象类进行编程,调用在目标抽象类中定义的方法: 95 | for animal in animals: 96 | print animal.name, animal.make_noise() 97 | 98 | # Cat meow ~ 99 | # Dog woof ! 100 | # Human hello ? 101 | -------------------------------------------------------------------------------- /02_structural_pattern/02_bridge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 桥接模式(Bridge Pattern) 6 | 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 7 | 8 | 包含四个角色 9 | [Abstraction][抽象类] 10 | 定义了一个实现类接口类型的对象并可以维护该对象; 11 | [RefinedAbstraction][扩充抽象类] 12 | 扩充由抽象类定义的接口,它实现了在抽象类中定义的抽象业务方法,在扩充抽象类中可以调用在实现类接口中定义的业务方法; 13 | [AbstractImplementor][实现类接口] 14 | 定义了实现类的接口,实现类接口仅提供基本操作,而抽象类定义的接口可能会做更多更复杂的操作; 15 | [ConcreteImplementor][具体实现类] 16 | 实现实现类接口,在不同的具体实现类中提供基本操作的不同实现, 17 | 在程序运行时,具体实现类对象将替换其父类对象,提供给客户端具体的业务操作方法。 18 | 19 | 在桥接模式中,抽象化(Abstraction)与实现化(Implementation)脱耦,它们可以沿着各自的维度独立变化。 20 | 21 | 优点 22 | 分离抽象接口及其实现部分,是比多继承方案更好的解决方法, 23 | 还提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统, 24 | 实现细节对客户透明,可以对用户隐藏实现细节; 25 | 26 | 缺点 27 | 增加系统的理解与设计难度,且识别出系统中两个独立变化的维度并不是一件容易的事情。 28 | 29 | 适用情况 30 | 需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系; 31 | 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响; 32 | 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展; 33 | 设计要求需要独立管理抽象化角色和具体化角色; 34 | 不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统。 35 | 36 | 桥接模式是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。 37 | """ 38 | 39 | class PhoneBrand(object): 40 | """ 41 | 抽象类 42 | """ 43 | def __init__(self): 44 | self.func = None 45 | def set_func(self, func): 46 | self.func = func 47 | def work(self): 48 | pass 49 | 50 | class PhoneBrand_ios(PhoneBrand): 51 | """ 52 | 扩充抽象类 53 | """ 54 | def work(self): 55 | if self.func is not None: 56 | self.func.run() 57 | 58 | class PhoneFunc(object): 59 | """ 60 | 实现类接口 61 | """ 62 | def run(self): 63 | pass 64 | 65 | class PhoneFunc_Call(PhoneFunc): 66 | """ 67 | 具体实现类 68 | """ 69 | def run(self): 70 | print self.__class__.__name__, 'run CALL' 71 | 72 | class PhoneFunc_Sms(PhoneFunc): 73 | """ 74 | 具体实现类 75 | """ 76 | def run(self): 77 | print self.__class__.__name__, 'run SMS' 78 | 79 | 80 | phone_ios = PhoneBrand_ios() 81 | 82 | func_a = PhoneFunc_Call() 83 | phone_ios.set_func(func_a) 84 | phone_ios.work() 85 | # PhoneFunc_Call run CALL 86 | 87 | func_b = PhoneFunc_Sms() 88 | phone_ios.set_func(func_b) 89 | phone_ios.work() 90 | # PhoneFunc_Sms run SMS 91 | -------------------------------------------------------------------------------- /02_structural_pattern/03_decorator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 装饰模式(Decorator Pattern) 6 | 动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。 7 | 8 | 包含四个角色 9 | [AbstractComponent][抽象构件] 10 | 定义了对象的接口,可以给这些对象动态增加职责(方法); 11 | [ConcreteComponent][具体构件] 12 | 定义了具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法); 13 | [AbstractDecorator][抽象装饰类] 14 | 是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现; 15 | [ConcreteDecorator][具体装饰类] 16 | 是抽象装饰类的子类,负责向构件添加新的职责。 17 | 18 | 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。 19 | 装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。 20 | 21 | 优点 22 | 可以提供比继承更多的灵活性,可以通过一种动态的方式来扩展一个对象的功能, 23 | 并通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合, 24 | 而且具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类; 25 | 26 | 缺点 27 | 使用装饰模式进行系统设计时将产生很多小对象,而且装饰模式比继承更加易于出错,排错也很困难, 28 | 对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。 29 | 30 | 适用情况 31 | 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责; 32 | 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销; 33 | 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。 34 | 35 | 装饰模式可分为透明装饰模式和半透明装饰模式: 36 | 在透明装饰模式中,要求客户端完全针对抽象编程,装饰模式的透明性要求客户端程序不应该声明具体构件类型和具体装饰类型,而应该全部声明为抽象构件类型; 37 | 半透明装饰模式允许用户在客户端声明具体装饰者类型的对象,调用在具体装饰者中新增的方法。 38 | 39 | 其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。 40 | 根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。 41 | """ 42 | 43 | class Person(object): 44 | """ 45 | 抽象构件 46 | """ 47 | def display(self): 48 | pass 49 | 50 | class Man(Person): 51 | """ 52 | 具体构件 53 | """ 54 | def __init__(self, name=None): 55 | self.name = name 56 | def display(self): 57 | return self.name 58 | 59 | class Superhero(Person): 60 | """ 61 | 抽象装饰类 62 | """ 63 | def __init__(self): 64 | self.component = None 65 | def decorate(self, component): 66 | self.component = component 67 | def behave(self): 68 | pass 69 | 70 | class Batman(Superhero): 71 | """ 72 | 具体装饰类 73 | """ 74 | def behave(self): 75 | return '^^^(B) [%s] (B)^^^' % self.component.display() 76 | 77 | class Superman(Superhero): 78 | """ 79 | 具体装饰类 80 | """ 81 | def behave(self): 82 | return '<<<(S) [%s] (S)>>>' % self.component.display() 83 | 84 | 85 | bruce = Man('Bruce') 86 | batman = Batman() 87 | batman.decorate(bruce) 88 | print batman.behave() 89 | # ^^^(B) [Bruce] (B)^^^ 90 | 91 | clark = Man('Clark') 92 | superman = Superman() 93 | superman.decorate(clark) 94 | print superman.behave() 95 | # <<<(S) [Clark] (S)>>> 96 | -------------------------------------------------------------------------------- /02_structural_pattern/04_facade.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 外观模式(Facade Pattern) 6 | 外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面, 7 | 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 8 | 9 | 包含两个角色 10 | [Facade][外观角色] 11 | 是在客户端直接调用的角色,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任, 12 | 它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理; 13 | [SubSystem][子系统角色] 14 | 在软件系统中可以同时有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能。 15 | 16 | 外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开, 17 | 使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。 18 | 19 | 优点 20 | 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易, 21 | 它实现了子系统与客户之间的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程; 22 | 23 | 缺点 24 | 不能很好地限制客户使用子系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。 25 | 26 | 适用情况 27 | 要为一个复杂子系统提供一个简单接口; 28 | 客户程序与多个子系统之间存在很大的依赖性; 29 | 在层次化结构中,需要定义系统中每一层的入口,使得层与层之间不直接产生联系。 30 | 31 | 外观模式又称为门面模式,它是一种对象结构型模式。 32 | """ 33 | 34 | class Tall(object): 35 | """ 36 | 子系统角色 37 | """ 38 | def behave(self): 39 | print self.__class__.__name__ 40 | 41 | class Rich(object): 42 | """ 43 | 子系统角色 44 | """ 45 | def behave(self): 46 | print self.__class__.__name__ 47 | 48 | class Handsome(object): 49 | """ 50 | 子系统角色 51 | """ 52 | def behave(self): 53 | print self.__class__.__name__ 54 | 55 | class Facade(object): 56 | """ 57 | 外观角色 58 | """ 59 | def __init__(self): 60 | self.tall = Tall() 61 | self.rich = Rich() 62 | self.handsome = Handsome() 63 | 64 | def show_body(self): 65 | self.tall.behave() 66 | self.handsome.behave() 67 | 68 | def show_financial(self): 69 | self.rich.behave() 70 | 71 | 72 | facade = Facade() 73 | facade.show_body() 74 | # Tall 75 | # Handsome 76 | facade.show_financial() 77 | # Rich 78 | -------------------------------------------------------------------------------- /02_structural_pattern/05_flyweight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 享元模式(Flyweight Pattern) 6 | 运用共享技术有效地支持大量细粒度对象的复用。 7 | 系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。 8 | 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。 9 | 10 | 包含四个角色 11 | [AbstractFlyweight][抽象享元类] 12 | 声明一个接口,通过它可以接受并作用于外部状态; 13 | [ConcreteFlyweight][具体享元类] 14 | 实现了抽象享元接口,其实例称为享元对象; 15 | [UnsharedConcreteFlyweight][非共享具体享元类] 16 | 是不能被共享的抽象享元类的子类; 17 | [FlyweightFactory][享元工厂类] 18 | 用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中。 19 | 20 | 享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态和外部状态。 21 | 其中内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享; 22 | 外部状态是随环境改变而改变的、不可以共享的状态。 23 | 24 | 优点 25 | 它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份; 26 | 27 | 缺点 28 | 使得系统更加复杂,并且需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。 29 | 30 | 适用情况 31 | 一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费; 32 | 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中; 33 | 多次重复使用享元对象。 34 | """ 35 | 36 | class Flyweight_abstract(object): 37 | """ 38 | 抽象享元类 39 | """ 40 | def work(self): 41 | pass 42 | 43 | class Flyweight_concrete_shared(Flyweight_abstract): 44 | """ 45 | 具体享元类(共享的) 46 | """ 47 | def __init__(self, role): 48 | self.role = role 49 | def work(self, name): 50 | print '(%s) [%s] [%s]' % (self.__class__.__name__, self.role, name) 51 | 52 | # class Flyweight_concrete_unshared(Flyweight_abstract): 53 | # """ 54 | # 具体享元类(非共享的) 55 | # """ 56 | # def __init__(self, role): 57 | # self.role = role 58 | # self.name = None 59 | # 60 | # def work(self, name): 61 | # self.name = name 62 | # print '(%s) [%s] [%s]' % (self.__class__.__name__, self.role, name) 63 | 64 | class Flyweight_Factory_shared(object): 65 | """ 66 | 享元工厂类 67 | """ 68 | def __init__(self): 69 | self.pool = {} 70 | self.count = {} 71 | def get_flyweight(self, role): 72 | if role not in self.pool: 73 | flyweight = Flyweight_concrete_shared(role) 74 | print '(%s): %s created' % (self.__class__.__name__, flyweight) 75 | self.pool[role] = flyweight 76 | self.count[role] = 1 77 | else: 78 | flyweight = self.pool[role] 79 | print '(%s): %s shared' % (self.__class__.__name__, flyweight) 80 | self.count[role] += 1 81 | return flyweight 82 | def get_count(self): 83 | print [(role, self.count[role]) for role in self.pool] 84 | 85 | # class Flyweight_Factory_unshared(object): 86 | # """ 87 | # 享元工厂类 88 | # """ 89 | # def __init__(self): 90 | # self.pool = [] 91 | # self.count = 0 92 | # def get_flyweight(self, role): 93 | # flyweight = Flyweight_concrete_unshared(role) 94 | # print '(%s): %s created' % (self.__class__.__name__, flyweight) 95 | # self.pool.append(flyweight) 96 | # self.count += 1 97 | # return flyweight 98 | # def get_count(self): 99 | # print self.count 100 | 101 | 102 | print '------------------------------------------------------------------------------------------' 103 | factory = Flyweight_Factory_shared() 104 | 105 | flyweight = factory.get_flyweight('soldier') 106 | # (Flyweight_Factory_shared): <__main__.Flyweight_concrete_shared object at 0x1092f1dd0> created 107 | flyweight.work('Captain Price') 108 | # (Flyweight_concrete_shared) [soldier] [Captain Price] 109 | 110 | flyweight = factory.get_flyweight('soldier') 111 | # (Flyweight_Factory_shared): <__main__.Flyweight_concrete_shared object at 0x1092f1dd0> shared 112 | flyweight.work('Soup Mactavish') 113 | # (Flyweight_concrete_shared) [soldier] [Soup Mactavish] 114 | 115 | flyweight = factory.get_flyweight('samurai') 116 | # (Flyweight_Factory_shared): <__main__.Flyweight_concrete_shared object at 0x1092f1e10> created 117 | flyweight.work('Himura Kenshin') 118 | # (Flyweight_concrete_shared) [samurai] [Himura Kenshin] 119 | 120 | print factory.pool 121 | # {'soldier': <__main__.Flyweight_concrete_shared object at 0x1092f1dd0>, 122 | # 'samurai': <__main__.Flyweight_concrete_shared object at 0x1092f1e10>} 123 | factory.get_count() 124 | # [('soldier', 2), ('samurai', 1)] 125 | print '------------------------------------------------------------------------------------------' 126 | # factory = Flyweight_Factory_unshared() 127 | # 128 | # flyweight = factory.get_flyweight('soldier') 129 | # # (Flyweight_Factory_unshared): <__main__.Flyweight_concrete_unshared object at 0x101cc2090> created 130 | # flyweight.work('Captain Price') 131 | # # (Flyweight_concrete_unshared) [soldier] [Captain Price] 132 | # 133 | # flyweight = factory.get_flyweight('soldier') 134 | # # (Flyweight_Factory_unshared): <__main__.Flyweight_concrete_unshared object at 0x101cc2150> created 135 | # flyweight.work('Soup Mactavish') 136 | # # (Flyweight_concrete_unshared) [soldier] [Soup Mactavish] 137 | # 138 | # flyweight = factory.get_flyweight('samurai') 139 | # # (Flyweight_Factory_unshared): <__main__.Flyweight_concrete_unshared object at 0x101cc2110> created 140 | # flyweight.work('Himura Kenshin') 141 | # # (Flyweight_concrete_unshared) [samurai] [Himura Kenshin] 142 | # 143 | # print factory.pool 144 | # # [<__main__.Flyweight_concrete_unshared object at 0x101cc2090>, 145 | # # <__main__.Flyweight_concrete_unshared object at 0x101cc2150>, 146 | # # <__main__.Flyweight_concrete_unshared object at 0x101cc2110>] 147 | # factory.get_count() 148 | # # 3 149 | print '------------------------------------------------------------------------------------------' 150 | -------------------------------------------------------------------------------- /02_structural_pattern/06_proxy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 代理模式(Proxy Pattern) 6 | 给某一个对象提供一个代理,并由代理对象控制对原对象的引用。 7 | 8 | 包含三个角色 9 | [AbstractSubject][抽象主题] 10 | 声明了真实主题和代理主题的共同接口; 11 | [RealSubject][真实主题] 12 | 定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作, 13 | 客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。 14 | [Proxy][代理] 15 | 内部包含对真实主题的引用,从而可以在任何时候操作真实主题对象; 16 | 17 | 优点 18 | 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度; 19 | 20 | 缺点 21 | 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢, 22 | 并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。 23 | 24 | 远程代理 25 | 远程代理可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。 26 | 客户完全可以认为被代理的远程业务对象是局域的而不是远程的,而远程代理对象承担了大部分的网络通信工作。 27 | 28 | 虚拟代理 29 | 当一个对象的加载十分耗费资源的时候,虚拟代理的优势就非常明显地体现出来了。 30 | 虚拟代理模式是一种内存节省技术,那些占用大量内存或处理复杂的对象将推迟到使用它的时候才创建。 31 | 32 | 保护代理 33 | 可以控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。 34 | 35 | 代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。 36 | """ 37 | 38 | class Subject(object): 39 | """ 40 | 抽象主题 41 | """ 42 | def request(self): 43 | pass 44 | 45 | class RealSubject(Subject): 46 | """ 47 | 真实主题 48 | """ 49 | def request(self): 50 | print '(%s) this is the real request' % self.__class__.__name__ 51 | 52 | class Proxy(Subject): 53 | """ 54 | 代理 55 | """ 56 | def __init__(self): 57 | self.real_subject = RealSubject() 58 | def request(self): 59 | self.real_subject.request() 60 | 61 | 62 | proxy = Proxy() 63 | proxy.request() 64 | # (RealSubject) this is the real request 65 | -------------------------------------------------------------------------------- /02_structural_pattern/07_composite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 组合模式(Composite Pattern) 6 | 组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次。 7 | 它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。 8 | 9 | 包含三个角色 10 | [Component][对象声明接口] 11 | 在适当的情况下,实现所有类共有接口的默认行为。 12 | 声明接口用于访问和管理Component子部件。 13 | [Leaf][叶子对象] 14 | 叶子结点,没有子结点。 15 | [Composite][容器对象] 16 | 定义有枝节点行为,用来存储子部件,在对象声明接口中实现与子部件有关操作,如增加(add)和删除(remove)等。 17 | 18 | 在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和容器对象实现相同的接口。 19 | 这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。 20 | 21 | 优点 22 | 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。 23 | 客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。 24 | 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合, 25 | 这样不断递归下去,可以形成复杂的树形结构。 26 | 更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。 27 | 28 | 缺点 29 | 使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联。 30 | 31 | 适用情况 32 | 需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。 33 | 让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。 34 | """ 35 | 36 | class Component(object): 37 | """ 38 | 对象声明接口 39 | """ 40 | def __init__(self, name): 41 | self.name = name 42 | def add(self, component): 43 | pass 44 | def remove(self, component): 45 | pass 46 | def display(self, depth): 47 | pass 48 | 49 | class Leaf(Component): 50 | """ 51 | 叶子对象 52 | """ 53 | def add(self, component): 54 | print '(Leaf can not add)' 55 | def remove(self, component): 56 | print '(Leaf can not remove)' 57 | def display(self, depth): 58 | print '|-----|' * depth + '[(%s) %s]' % (self.__class__.__name__, self.name) 59 | 60 | class Composite(Component): 61 | """ 62 | 容器对象 63 | """ 64 | def __init__(self, name): 65 | self.name = name 66 | self.children = [] 67 | def add(self, component): 68 | self.children.append(component) 69 | def remove(self, component): 70 | if component in self.children: 71 | self.children.remove(component) 72 | def display(self, depth): 73 | print '|-----|' * depth + '[(%s) %s]' % (self.__class__.__name__, self.name) 74 | for child in self.children: 75 | child.display(depth+1) 76 | 77 | 78 | node_0 = Composite('A') 79 | node_1_1 = Leaf('B') 80 | node_1_2 = Composite('C') 81 | node_1_3 = Leaf('D') 82 | node_0.add(node_1_1) 83 | node_0.add(node_1_2) 84 | node_0.add(node_1_3) 85 | 86 | node_2_1 = Leaf('E') 87 | node_2_2 = Leaf('F') 88 | node_1_2.add(node_2_1) 89 | node_1_2.add(node_2_2) 90 | 91 | node_0.display(0) 92 | # [(Composite) A] 93 | # |-----|[(Leaf) B] 94 | # |-----|[(Composite) C] 95 | # |-----||-----|[(Leaf) E] 96 | # |-----||-----|[(Leaf) F] 97 | # |-----|[(Leaf) D] 98 | -------------------------------------------------------------------------------- /03_behavioral_pattern/01_responsibility_chain.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 责任链模式(Chain of Responsibility) 6 | 很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。 7 | 8 | 包含两个角色 9 | [AbstractHandler][抽象处理者] 10 | 定义了一个处理请求的方法; 11 | 所有的具体处理者都必须实现该抽象类; 12 | [ConcreteHandler][具体处理者] 13 | 处理它所负责的请求,同时也可以访问它的后继者; 14 | 如果它能够处理该请求则处理,否则将请求传递到它的后继者; 15 | 16 | 优点 17 | 实现了请求者与处理者代码分离: 18 | 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求, 19 | 这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任,提高系统的灵活性和可扩展行。 20 | 21 | 缺点 22 | 每次都是从链头开始。 23 | 24 | 责任链模式强调的是每一个对象及其对下家的引用来组成一条链,利用这种方式将发送者和接收者解耦。 25 | """ 26 | 27 | class Handler(object): 28 | """ 29 | 抽象处理者 30 | """ 31 | def __init__(self): 32 | self.successor = None 33 | def handle(self, request): 34 | pass 35 | def set_successor(self, successor): 36 | self.successor = successor 37 | 38 | class Handler_concrete_1(Handler): 39 | """ 40 | 具体处理者 41 | """ 42 | def handle(self, request): 43 | if request <= 10: 44 | print '(request:%s) %s handled' % (request, self.__class__.__name__) 45 | else: 46 | self.successor.handle(request) 47 | 48 | class Handler_concrete_2(Handler): 49 | """ 50 | 具体处理者 51 | """ 52 | def handle(self, request): 53 | if request > 10 and request <= 20: 54 | print '(request:%s) %s handled' % (request, self.__class__.__name__) 55 | else: 56 | self.successor.handle(request) 57 | 58 | class Handler_concrete_3(Handler): 59 | """ 60 | 具体处理者 61 | """ 62 | def handle(self, request): 63 | if request > 20: 64 | print '(request:%s) %s handled' % (request, self.__class__.__name__) 65 | else: 66 | self.successor.handle(request) 67 | 68 | 69 | h1 = Handler_concrete_1() 70 | h2 = Handler_concrete_2() 71 | h3 = Handler_concrete_3() 72 | h1.set_successor(h2) 73 | h2.set_successor(h3) 74 | 75 | requests = [5, 15, 25] 76 | for request in requests: 77 | h1.handle(request) 78 | 79 | # (request:5) Handler_concrete_1 handled 80 | # (request:15) Handler_concrete_2 handled 81 | # (request:25) Handler_concrete_3 handled 82 | -------------------------------------------------------------------------------- /03_behavioral_pattern/02_command.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 命令模式(Command Pattern) 6 | 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化; 7 | 对请求排队或者记录请求日志,以及支持可撤销的操作。 8 | 9 | 包含四个角色 10 | [AbstractCommand][抽象命令类] 11 | 声明执行操作的接口; 12 | [ConcreteCommand][具体命令类] 13 | 是抽象命令类的子类,实现了在抽象命令类中声明的方法; 14 | 它拥有一个接收者对象,将接收者对象的动作绑定其中; 15 | 通过调用接收者对象的动作,执行相应的操作; 16 | [Invoker][调用者] 17 | 即请求的发送者,又称为请求者,它通过命令对象来执行请求; 18 | [Receiver][接收者] 19 | 执行与请求相关的操作,它具体实现对请求的业务处理; 20 | 21 | 命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。 22 | 命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。 23 | 24 | 优点 25 | 降低系统的耦合度,增加新的命令很方便,而且可以比较容易地设计一个命令队列和宏命令,并方便地实现对请求的撤销和恢复; 26 | 27 | 缺点 28 | 可能会导致某些系统有过多的具体命令类。 29 | 30 | 适用情况 31 | 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互; 32 | 需要在不同的时间指定请求、将请求排队和执行请求; 33 | 需要支持命令的撤销操作和恢复操作,需要将一组操作组合在一起,即支持宏命令。 34 | 35 | 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。 36 | """ 37 | 38 | class Invoker(object): 39 | """ 40 | 调用者 41 | """ 42 | def __init__(self, command): 43 | self.command = command 44 | def call(self): 45 | print '%s call()' % self.__class__.__name__, 46 | self.command.execute() 47 | 48 | class Command_abstract(object): 49 | """ 50 | 抽象命令类 51 | """ 52 | def execute(self): 53 | pass 54 | 55 | class Command_concrete(Command_abstract): 56 | """ 57 | 具体命令类 58 | """ 59 | def __init__(self, receiver): 60 | self.receiver = receiver 61 | def execute(self): 62 | print '%s execute()' % self.__class__.__name__, 63 | self.receiver.action() 64 | 65 | class Receiver(object): 66 | """ 67 | 接收者 68 | """ 69 | def action(self): 70 | print '%s action()' % self.__class__.__name__, 71 | print 'this is receiver action ...' 72 | 73 | 74 | receiver = Receiver() 75 | command_concrete = Command_concrete(receiver) 76 | invoker = Invoker(command_concrete) 77 | invoker.call() 78 | 79 | # Invoker call() 80 | # Command_concrete execute() 81 | # Receiver action() 82 | # this is receiver action ... 83 | -------------------------------------------------------------------------------- /03_behavioral_pattern/03_mediator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 中介者模式(Mediator Pattern) 6 | 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 7 | 8 | 式包含四个角色 9 | [AbstractMediator][抽象中介者] 10 | 定义一个接口,该接口用于与各同事对象之间的通信; 11 | [ConcreteMediator][具体中介者] 12 | 是抽象中介者的子类,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事对象的引用; 13 | [AbstractColleague][抽象同事类] 14 | 定义各同事的公有方法; 15 | [ConcreteColleague][具体同事类] 16 | 是抽象同事类的子类,在具体同事类中实现了在抽象同事类中定义的方法; 17 | 每一个同事对象都引用一个中介者对象; 18 | 每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信; 19 | 20 | 通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,中介者承担了中转作用和协调作用。 21 | 中介者类是中介者模式的核心,它对整个系统进行控制和协调,简化了对象之间的交互,还可以对对象间的交互进行进一步的控制。 22 | 23 | 优点 24 | 简化了对象之间的交互,将各同事解耦,还可以减少子类生成,对于复杂的对象之间的交互,通过引入中介者,可以简化各同事类的设计和实现; 25 | 26 | 缺点 27 | 具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。 28 | 29 | 适用情况 30 | 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解; 31 | 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象; 32 | 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。 33 | 34 | 中介者模式又称为调停者模式,它是一种对象行为型模式。 35 | """ 36 | 37 | class Colleage_abstract(object): 38 | """ 39 | 抽象同事类 40 | """ 41 | def __init__(self, mediator): 42 | self.mediator = mediator 43 | def send(self, target, msg): 44 | pass 45 | def receive(self, source, msg): 46 | pass 47 | 48 | class Colleage_concrete_A(Colleage_abstract): 49 | """ 50 | 具体同事类 51 | """ 52 | def send(self, target, msg): 53 | print '%s send to %s: %s' % (self, target, msg) 54 | self.mediator.forward(self, target, msg) 55 | def receive(self, source, msg): 56 | print '%s receive from %s: %s' % (self, source, msg) 57 | 58 | class Colleage_concrete_B(Colleage_abstract): 59 | """ 60 | 具体同事类 61 | """ 62 | def send(self, target, msg): 63 | print '%s send to %s: %s' % (self, target, msg) 64 | self.mediator.forward(self, target, msg) 65 | def receive(self, source, msg): 66 | print '%s receive from %s: %s' % (self, source, msg) 67 | 68 | class Mediator_abstract(object): 69 | """ 70 | 抽象中介者 71 | """ 72 | def forward(self): 73 | pass 74 | 75 | class Mediator_concrete(Mediator_abstract): 76 | """ 77 | 具体中介者 78 | """ 79 | def forward(self, source, target, msg): 80 | target.receive(source, msg) 81 | 82 | 83 | mediator = Mediator_concrete() 84 | colleage_a = Colleage_concrete_A(mediator) 85 | colleage_b = Colleage_concrete_B(mediator) 86 | 87 | colleage_a.send(colleage_b, 'How are you ?') 88 | # <__main__.Colleage_concrete_A object at 0x107dbb090> send to <__main__.Colleage_concrete_B object at 0x107dbb0d0>: How are you ? 89 | # <__main__.Colleage_concrete_B object at 0x107dbb0d0> receive from <__main__.Colleage_concrete_A object at 0x107dbb090>: How are you ? 90 | 91 | colleage_b.send(colleage_a, 'Fine, thank you, and you ?') 92 | # <__main__.Colleage_concrete_B object at 0x107dbb0d0> send to <__main__.Colleage_concrete_A object at 0x107dbb090>: Fine, thank you, and you ? 93 | # <__main__.Colleage_concrete_A object at 0x107dbb090> receive from <__main__.Colleage_concrete_B object at 0x107dbb0d0>: Fine, thank you, and you ? 94 | -------------------------------------------------------------------------------- /03_behavioral_pattern/04_observer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 观察者模式(Observer Pattern) 6 | 定义对象间的一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。 7 | 8 | 包含四个角色 9 | [Subject][目标] 10 | 又称为主题,它是指被观察的对象; 11 | 他把所有对观察者的引用保存在一个聚集里,每一个主题都可以有多个观察者; 12 | [ConcreteSubject][具体目标] 13 | 是目标类的子类, 14 | 通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知; 15 | [Observer][观察者] 16 | 将对观察目标的改变做出反应; 17 | 为所有的具体观察者定义一个接口,在得到目标的通知时能够及时的更新自己; 18 | [ConcreteObserver][具体观察者] 19 | 维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致; 20 | 21 | 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象, 22 | 当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。 23 | 24 | 优点 25 | 可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立一个抽象的耦合,支持广播通信; 26 | 27 | 缺点 28 | 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间, 29 | 而且如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 30 | 31 | 适用情况 32 | 一个抽象模型有两个方面,其中一个方面依赖于另一个方面; 33 | 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变; 34 | 一个对象必须通知其他对象,而并不知道这些对象是谁; 35 | 需要在系统中创建一个触发链。 36 | 37 | 观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。 38 | 观察者模式是一种对象行为型模式。 39 | """ 40 | 41 | class Subject(object): 42 | """ 43 | 目标 44 | """ 45 | def __init__(self): 46 | self.observer_list = [] 47 | def attach(self, observer): 48 | if observer not in self.observer_list: 49 | self.observer_list.append(observer) 50 | def detach(self, observer): 51 | if observer in self.observer_list: 52 | self.observer_list.remove(observer) 53 | def notify(self): 54 | for observer in self.observer_list: 55 | print '%s notifying %s' % (self, observer) 56 | observer.update() 57 | 58 | class Subject_concrete(Subject): 59 | """ 60 | 具体目标 61 | """ 62 | def __init__(self): 63 | super(Subject_concrete, self).__init__() 64 | self._data = None 65 | @property 66 | def data(self): 67 | return self._data 68 | @data.setter 69 | def data(self, value): 70 | self._data = value 71 | """ 72 | 数据发生改变时,向所有观察者发出通知 73 | """ 74 | self.notify() 75 | @data.deleter 76 | def data(self): 77 | del self._data 78 | 79 | class Observer(object): 80 | """ 81 | 观察者 82 | """ 83 | def __init__(self, subject): 84 | self.subject = subject 85 | def update(self): 86 | pass 87 | 88 | class Observer_concrete(Observer): 89 | """ 90 | 具体观察者 91 | """ 92 | def update(self): 93 | print '%s get notified from %s new data = %s' % (self, self.subject, self.subject.data) 94 | 95 | 96 | subject = Subject_concrete() 97 | observer_1 = Observer_concrete(subject) 98 | observer_2 = Observer_concrete(subject) 99 | subject.attach(observer_1) 100 | subject.attach(observer_2) 101 | 102 | subject.data = 1 103 | # <__main__.Subject_concrete object at 0x101c93050> notifying <__main__.Observer_concrete object at 0x101c930d0> 104 | # <__main__.Observer_concrete object at 0x101c930d0> get notified from <__main__.Subject_concrete object at 0x101c93050> new data = 1 105 | # <__main__.Subject_concrete object at 0x101c93050> notifying <__main__.Observer_concrete object at 0x101c93110> 106 | # <__main__.Observer_concrete object at 0x101c93110> get notified from <__main__.Subject_concrete object at 0x101c93050> new data = 1 107 | 108 | subject.data = 2 109 | # <__main__.Subject_concrete object at 0x101c93050> notifying <__main__.Observer_concrete object at 0x101c930d0> 110 | # <__main__.Observer_concrete object at 0x101c930d0> get notified from <__main__.Subject_concrete object at 0x101c93050> new data = 2 111 | # <__main__.Subject_concrete object at 0x101c93050> notifying <__main__.Observer_concrete object at 0x101c93110> 112 | # <__main__.Observer_concrete object at 0x101c93110> get notified from <__main__.Subject_concrete object at 0x101c93050> new data = 2 113 | -------------------------------------------------------------------------------- /03_behavioral_pattern/05_state.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 状态模式(State Pattern) 6 | 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。 7 | 8 | 包含三个角色 9 | [Context][环境类] 10 | 又称为上下文类,它是拥有状态的对象, 11 | 在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态, 12 | 在具体实现时,它是一个State子类的对象,可以定义初始状态; 13 | [AbstractState][抽象状态类] 14 | 定义一个接口以封装与环境类的一个特定状态相关的行为; 15 | [ConcreteState][具体状态类] 16 | 是抽象状态类的子类, 17 | 每一个子类实现一个与环境类的一个状态相关的行为, 18 | 每一个具体状态类对应环境的一个具体状态,不同的具体状态类其行为有所不同; 19 | 20 | 状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的行为。 21 | 22 | 优点 23 | 封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态, 24 | 只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数; 25 | 26 | 缺点 27 | 使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂, 28 | 如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。 29 | 30 | 适用情况 31 | 对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为; 32 | 代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差, 33 | 不能方便地增加和删除状态,使客户类与类库之间的耦合增强。 34 | 35 | 其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。 36 | """ 37 | 38 | class Context(object): 39 | """ 40 | 环境类 41 | """ 42 | def __init__(self): 43 | self.state = None 44 | self.state_a = State_concrete_A() 45 | self.state_b = State_concrete_B() 46 | self.state_c = State_concrete_C() 47 | def change_state(self, state): 48 | self.state = state 49 | def request(self): 50 | if self.data <= 10: 51 | self.change_state(self.state_a) 52 | elif self.data <= 20: 53 | self.change_state(self.state_b) 54 | else: 55 | self.change_state(self.state_c) 56 | print 'requesting state: %s %s' % (self.state, id(self.state)) 57 | self.state.handle(self) 58 | 59 | class State_abstract(object): 60 | """ 61 | 抽象状态类 62 | """ 63 | def handle(self, context): 64 | pass 65 | 66 | class State_concrete_A(State_abstract): 67 | """ 68 | 具体状态类 69 | """ 70 | def handle(self, context): 71 | print 'handle state A' 72 | 73 | class State_concrete_B(State_abstract): 74 | """ 75 | 具体状态类 76 | """ 77 | def handle(self, context): 78 | print 'handle state B' 79 | 80 | class State_concrete_C(State_abstract): 81 | """ 82 | 具体状态类 83 | """ 84 | def handle(self, context): 85 | print 'handle state C' 86 | 87 | 88 | context = Context() 89 | 90 | context.data = 1 91 | context.request() 92 | # requesting state: <__main__.State_concrete_A object at 0x103601110> 4351594768 93 | # handle state A 94 | 95 | context.data = 5 96 | context.request() 97 | # requesting state: <__main__.State_concrete_A object at 0x103601110> 4351594768 98 | # handle state A 99 | 100 | context.data = 15 101 | context.request() 102 | # requesting state: <__main__.State_concrete_B object at 0x103601150> 4351594832 103 | # handle state B 104 | 105 | context.data = 25 106 | context.request() 107 | # requesting state: <__main__.State_concrete_C object at 0x103601190> 4351594896 108 | # handle state C 109 | -------------------------------------------------------------------------------- /03_behavioral_pattern/06_strategy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 策略模式(Strategy Pattern) 6 | 定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。 7 | 策略模式让算法独立于使用它的客户而变化。 8 | 9 | 包含三个角色 10 | [Context][环境类] 11 | 维护一个策略类对象的引用,用一个具体策略类来配置; 12 | 定义了调用策略类算法的方法; 13 | [AbstractStrategy][抽象策略类] 14 | 是所有策略类的父类,为具体策略类所支持的算法声明了接口; 15 | 环境类使用这个接口来调用某个具体策略类中定义的算法; 16 | [ConcreteStrategy][具体策略类] 17 | 实现了在抽象策略类中定义的算法; 18 | 19 | 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派给不同的对象管理。 20 | 策略模式通常把一个系列的算法封装到一系列的策略类里面,作为一个抽象策略类的子类。 21 | 22 | 优点 23 | 对“开闭原则”的完美支持,在不修改原有系统的基础上可以更换算法或者增加新的算法, 24 | 它很好地管理算法族,提高了代码的复用性,是一种替换继承,避免多重条件转移语句的实现方式; 25 | 26 | 缺点 27 | 客户端必须知道所有的策略类,并理解其区别, 28 | 同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。 29 | 30 | 适用情况 31 | 在一个系统里面有许多类,它们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为; 32 | 一个系统需要动态地在几种算法中选择一种; 33 | 避免使用难以维护的多重条件选择语句; 34 | 希望在具体策略类中封装算法和与相关的数据结构。 35 | 36 | 也称为政策模式(Policy),是一种对象行为型模式。 37 | """ 38 | 39 | class Context(object): 40 | """ 41 | 环境类 42 | """ 43 | def __init__(self): 44 | self.strategy = None 45 | def set_strategy(self, strategy): 46 | self.strategy = strategy 47 | def apply_strategy(self): 48 | self.strategy.algorithm() 49 | 50 | class Strategy_abstract(object): 51 | """ 52 | 抽象策略类 53 | """ 54 | def algorithm(self): 55 | pass 56 | 57 | class Strategy_concrete_A(Strategy_abstract): 58 | """ 59 | 具体策略类 60 | """ 61 | def algorithm(self): 62 | print 'algorithm A' 63 | 64 | class Strategy_concrete_B(Strategy_abstract): 65 | """ 66 | 具体策略类 67 | """ 68 | def algorithm(self): 69 | print 'algorithm B' 70 | 71 | 72 | context = Context() 73 | strategy_a = Strategy_concrete_A() 74 | strategy_b = Strategy_concrete_B() 75 | 76 | context.set_strategy(strategy_a) 77 | context.apply_strategy() 78 | # algorithm A 79 | 80 | context.set_strategy(strategy_b) 81 | context.apply_strategy() 82 | # algorithm B 83 | -------------------------------------------------------------------------------- /03_behavioral_pattern/07_interpreter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 解释器模式(Interpreter Pattern) 6 | 定义语言(使用规定格式和语法的代码)的文法,并且建立一个解释器来解释该语言中的句子。 7 | 8 | 包含四个角色 9 | [AbstractExpression][抽象表达式] 10 | 声明一个抽象的解释操作, 11 | 该接口为抽象语法树中所有的节点共享; 12 | [TerminalExpression][终结符表达式] 13 | 实现与文法中的终结符相关的解释操作; 14 | 实现抽象表达式中所要求的方法; 15 | 文法中每一个终结符都有一个具体的终结表达式与之相对应; 16 | 比如公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式; 17 | [NonterminalExpression][非终结符表达式] 18 | 实现与文法中的非终结符相关的解释操作; 19 | 对文法中的每一条规则,都需要一个具体的非终结符表达式类; 20 | 非终结符表达式一般是文法中的运算符或者其他关键字; 21 | 比如公式R=R1+R2,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式; 22 | [Context][环境类] 23 | 包含解释器之外的一些全局信息; 24 | 一般是用来存放文法中各个终结符所对应的具体值; 25 | 26 | 解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。 27 | 它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。 28 | 29 | 优点 30 | 可扩展性比较好,灵活。 31 | 增加了新的解释表达式的方式。 32 | 易于实现文法。 33 | 34 | 缺点 35 | 执行效率比较低,可利用场景比较少。 36 | 对于复杂的文法比较难维护。 37 | 38 | 适用情况 39 | 需要将一个需要解释执行的语言中的句子表示为一个抽象语法树。 40 | 一些重复出现的问题可以用一种简单的语言来进行表达。 41 | 文法较为简单。 42 | """ 43 | 44 | class AbstractExpression(object): 45 | """ 46 | 抽象表达式 47 | """ 48 | def to_string(self): 49 | pass 50 | def interpret(self, context): 51 | pass 52 | 53 | class Constant(AbstractExpression): 54 | """ 55 | (常量)终结符表达式 56 | """ 57 | def __init__(self, value): 58 | self.value = value 59 | def to_string(self): 60 | return str(bool(self.value)) 61 | def interpret(self, context): 62 | return self.value 63 | 64 | class Variable(AbstractExpression): 65 | """ 66 | (变量)终结符表达式 67 | """ 68 | def __init__(self, name): 69 | self.name = name 70 | def to_string(self): 71 | return str(self.name) 72 | def interpret(self, context): 73 | return context.lookup(self) 74 | 75 | class And(AbstractExpression): 76 | """ 77 | (逻辑与)非终结符表达式 78 | """ 79 | def __init__(self, left, right): 80 | self.left = left 81 | self.right = right 82 | def to_string(self): 83 | return '(%s AND %s)' % (self.left.to_string(), self.right.to_string()) 84 | def interpret(self, context): 85 | return self.left.interpret(context) and self.right.interpret(context) 86 | 87 | class Or(AbstractExpression): 88 | """ 89 | (逻辑或)非终结符表达式 90 | """ 91 | def __init__(self, left, right): 92 | self.left = left 93 | self.right = right 94 | def to_string(self): 95 | return '(%s OR %s)' % (self.left.to_string(), self.right.to_string()) 96 | def interpret(self, context): 97 | return self.left.interpret(context) or self.right.interpret(context) 98 | 99 | class Not(AbstractExpression): 100 | """ 101 | (逻辑非)非终结符表达式 102 | """ 103 | def __init__(self, exp): 104 | self.exp = exp 105 | def to_string(self): 106 | return '(NOT %s)' % (self.exp.to_string(),) 107 | def interpret(self, context): 108 | return not self.exp.interpret(context) 109 | 110 | class Context(object): 111 | """ 112 | 环境类 113 | """ 114 | def __init__(self): 115 | self.map = {} 116 | def assign(self, key, value): 117 | self.map[key] = value 118 | def lookup(self, key): 119 | return self.map.get(key) 120 | 121 | 122 | 123 | 124 | context = Context() 125 | 126 | constant_a = Constant(True) 127 | constant_b = Constant(False) 128 | variable_x = Variable('x') 129 | variable_y = Variable('y') 130 | context.assign(variable_x, True) 131 | context.assign(variable_y, False) 132 | 133 | expression = And(And(variable_x, constant_a), Not(Or(variable_y, constant_b))) 134 | 135 | print 'constant_a =', constant_a.to_string() 136 | print 'constant_b =', constant_b.to_string() 137 | print 'variable_x =', context.lookup(variable_x) 138 | print 'variable_y =', context.lookup(variable_y) 139 | # constant_a = True 140 | # constant_b = False 141 | # variable_x = True 142 | # variable_y = False 143 | print '%s = %s' % (expression.to_string(), expression.interpret(context)) 144 | # ((x AND True) AND (NOT (y OR False))) = True 145 | -------------------------------------------------------------------------------- /03_behavioral_pattern/08_iterator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 迭代器模式(Iterator Pattern) 6 | 提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部的表示。 7 | 8 | 包含四个角色 9 | [AbstractIterator][抽象迭代器] 10 | 所有迭代器都需要实现的接口,提供了游走聚合对象元素之间的方法; 11 | [ConcreteIterator][具体迭代器] 12 | 利用这个具体的迭代器能够对具体的聚合对象进行遍历; 13 | 每一个聚合对象都应该对应一个具体的迭代器; 14 | [AbstractAggregate][抽象聚合类] 15 | [ConcreteAggregate][具体聚合类] 16 | 实现 create_iterator() 方法,返回该聚合对象的迭代器; 17 | 18 | 迭代器模式是将迭代元素的责任交给迭代器,而不是聚合对象,我们甚至在不需要知道该聚合对象的内部结构就可以实现该聚合对象的迭代。 19 | 通过迭代器模式,使得聚合对象的结构更加简单,它不需要关注它元素的遍历,只需要专注它应该专注的事情,这样就更加符合单一职责原则了。 20 | 21 | 优点 22 | 它支持以不同的方式遍历一个聚合对象。 23 | 迭代器简化了聚合类。 24 | 在同一个聚合上可以有多个遍历。 25 | 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。 26 | 27 | 缺点 28 | 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类, 29 | 类的个数成对增加,这在一定程度上增加了系统的复杂性。 30 | 31 | 适用情况 32 | 访问一个聚合对象的内容而无须暴露它的内部表示。 33 | 需要为聚合对象提供多种遍历方式。 34 | 为遍历不同的聚合结构提供一个统一的接口。 35 | """ 36 | 37 | class Aggregate_abstract(object): 38 | """ 39 | 抽象聚合类 40 | """ 41 | def create_iterator(self): 42 | pass 43 | 44 | class Aggregate_concrete(Aggregate_abstract): 45 | """ 46 | 具体聚合类 47 | """ 48 | def __init__(self): 49 | self.iterator = None 50 | def create_iterator(self): 51 | self.iterator = Iterator_concrete() 52 | return self.iterator 53 | 54 | class Iterator_abstract(object): 55 | """ 56 | 抽象迭代器 57 | """ 58 | def first_item(self): 59 | pass 60 | def next_item(self): 61 | pass 62 | def has_next(self): 63 | pass 64 | def current_item(self): 65 | pass 66 | 67 | class Iterator_concrete(Iterator_abstract): 68 | """ 69 | 具体迭代器 70 | """ 71 | def __init__(self): 72 | self.container = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] 73 | self.position = 0 74 | def first_item(self): 75 | return self.container[0] 76 | def next_item(self): 77 | self.position += 1 78 | if self.position < len(self.container): 79 | return self.container[self.position] 80 | else: 81 | self.position = self.position % len(self.container) 82 | return self.container[self.position] 83 | def has_next(self): 84 | return self.position < len(self.container) - 1 85 | def current_item(self): 86 | return self.container[self.position] 87 | 88 | 89 | aggregate = Aggregate_concrete() 90 | iterator = aggregate.create_iterator() 91 | 92 | print iterator.first_item() 93 | # Monday 94 | 95 | for n in range(10): 96 | print iterator.next_item() 97 | 98 | # Tuesday 99 | # Wednesday 100 | # Thursday 101 | # Friday 102 | # Saturday 103 | # Sunday 104 | # Monday 105 | # Tuesday 106 | # Wednesday 107 | # Thursday 108 | -------------------------------------------------------------------------------- /03_behavioral_pattern/09_memento.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 备忘录模式(Memento Pattern) 6 | 在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。 7 | 8 | 包含三个角色 9 | [Originator][原发器] 10 | 负责创建一个备忘录,用以记录当前时刻对象的内部状态; 11 | 并可使用备忘录恢复内部状态; 12 | 同时原发器还可以根据需要决定备忘录存储原发器的哪些内部状态; 13 | [Memento][备忘录] 14 | 用于存储原发器对象的内部状态,并且可以防止原发器以外的对象访问备忘录。 15 | 在备忘录Memento中有两个接口, 16 | Caretaker只能看到备忘录中的窄接口,它只能将备忘录传递给其他对象。 17 | Originator可以看到宽接口,允许它访问返回到先前状态的所有数据。 18 | [Caretaker][负责人] 19 | 负责保存好备忘录。 20 | 不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。 21 | 22 | 23 | 在备忘录模式中,最重要的就是备忘录Memento了。 24 | 我们知道备忘录中存储的就是原发器的部分或者所有的状态信息,而这些状态信息是不能够被其他对象所访问了, 25 | 也就是说我们是不可能在备忘录之外的对象来存储这些状态信息,如果暴漏了内部状态信息就违反了封装的原则, 26 | 所以,只允许生成该备忘录的那个原发器访问备忘录的内部状态,除了原发器外的其他对象都不可以访问备忘录。 27 | 28 | 所以,为了实现备忘录模式的封装,我们需要对备忘录的访问做些控制: 29 | 对原发器:可以访问备忘录里的所有信息。 30 | 对负责人:不可以访问备忘录里面的数据,但是他可以保存备忘录并且可以将备忘录传递给其他对象。 31 | 其他对象:不可访问也不可以保存,它只负责接收从负责人那里传递过来的备忘录同时恢复原发器的状态。 32 | 33 | 优点 34 | 给用户提供了一种可以恢复状态的机制。可以使用户能够比较方便地回到某个历史的状态。 35 | 实现了信息的封装。使得用户不需要关心状态的保存细节。 36 | 37 | 缺点 38 | 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。 39 | 40 | 适用情况 41 | 需要保存一个对象在某一个时刻的状态或部分状态。 42 | 如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性, 43 | 一个对象不希望外界直接访问其内部状态,通过负责人可以间接访问其内部状态。 44 | """ 45 | 46 | import copy 47 | 48 | class Originator(object): 49 | """ 50 | 原发器 51 | """ 52 | def __init__(self): 53 | self.state = {} 54 | def get_state(self): 55 | return self.state 56 | def display(self): 57 | print '%s' % self, ['%s = %s' % (key, self.state[key]) for key in self.state] 58 | def create_memento(self): 59 | """ 60 | 在原发器中保存状态时必须使用深拷贝,否则备忘录中保存的状态和原发器中的状态是同一个 dict 对象, 61 | 备忘录中的状态会随原发器中状态变化而变化,无法恢复! 62 | """ 63 | return Memento(copy.deepcopy(self.state)) 64 | def restore_memento(self, memento): 65 | self.state = memento.state 66 | 67 | class Memento(object): 68 | """ 69 | 备忘录 70 | """ 71 | def __init__(self, state): 72 | self.state = state 73 | def get_state(self): 74 | return self.state 75 | 76 | class Caretaker(object): 77 | """ 78 | 负责人 79 | """ 80 | def __init__(self): 81 | self.memento = None 82 | def get_memento(self): 83 | return self.memento 84 | def set_memento(self, memento): 85 | self.memento = memento 86 | 87 | 88 | print '初始状态' 89 | my_obj = Originator() 90 | my_obj.state = {'hp': 999, 'mp': 999, 'exp': 999} 91 | my_obj.display() 92 | # <__main__.Originator object at 0x10a29c710> ['hp = 999', 'mp = 999', 'exp = 999'] 93 | 94 | print '保存状态' 95 | caretaker = Caretaker() 96 | memento = my_obj.create_memento() 97 | caretaker.set_memento(memento) 98 | 99 | print '状态变化' 100 | my_obj.state.update(hp=11, mp=22, exp=33) 101 | my_obj.display() 102 | # <__main__.Originator object at 0x10a29c710> ['mp = 22', 'exp = 33', 'hp = 11'] 103 | 104 | print '恢复状态' 105 | memento_restore = caretaker.get_memento() 106 | my_obj.restore_memento(memento_restore) 107 | my_obj.display() 108 | # <__main__.Originator object at 0x10a29c710> ['hp = 999', 'mp = 999', 'exp = 999'] 109 | -------------------------------------------------------------------------------- /03_behavioral_pattern/10_template_method.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 模板方法模式(Template Method Pattern) 6 | 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。 7 | 模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。 8 | 9 | 包含二个角色 10 | [AbstractClass][抽象类] 11 | 实现了一个模板,定义了算法的基本骨架, 12 | 具体子类将重定义 primitiveOperation() 方法以实现一个算法步骤。 13 | [ConcreteClass][具体子类] 14 | 实现 primitiveOperation() 方法以完成算法中与特定子类相关的步骤。 15 | 16 | 模板方法模式就是基于继承的代码复用技术的。 17 | 在模板方法模式中,我们可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中。 18 | 也就是说我们需要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数的形式实现, 19 | 然后声明一些抽象方法让子类来实现剩余的逻辑,不同的子类可以以不同的方式来实现这些逻辑。 20 | 所以模板方法的模板其实就是一个普通的方法,只不过这个方法是将算法实现的步骤封装起来的。 21 | 22 | 优点 23 | 定义了一组算法,将具体的实现交由子类负责。 24 | 是一种代码复用的基本技术。 25 | 导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。 26 | 27 | 缺点 28 | 每一个不同的实现都需要一个子类,导致类的个数增加,使得系统更加庞大。 29 | 30 | 适用情况 31 | 需要一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。 32 | 各子类中公共的行为应被提取出来,并集中到一个公共父类中以避免代码重复。 33 | """ 34 | 35 | class Beverage(object): 36 | """ 37 | 抽象类 38 | """ 39 | def prepare(self): 40 | print 'boil water' 41 | def brew(self): 42 | pass 43 | def serve(self): 44 | print 'serve %s: %s' % (self.__class__.__name__, self) 45 | def make(self): 46 | self.prepare() 47 | self.brew() 48 | self.serve() 49 | 50 | class Tea(Beverage): 51 | """ 52 | 具体子类 53 | """ 54 | def brew(self): 55 | print 'brew [tea]' 56 | 57 | class Coffee(Beverage): 58 | """ 59 | 具体子类 60 | """ 61 | def brew(self): 62 | print 'brew [coffee]' 63 | 64 | 65 | tea = Tea() 66 | tea.make() 67 | # boil water 68 | # brew [tea] 69 | # serve Tea: <__main__.Tea object at 0x10873fd50> 70 | 71 | coffee = Coffee() 72 | coffee.make() 73 | # boil water 74 | # brew [coffee] 75 | # serve Coffee: <__main__.Coffee object at 0x10873fd90> 76 | -------------------------------------------------------------------------------- /03_behavioral_pattern/11_visitor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding:utf-8 3 | 4 | """ 5 | 访问者模式(Visitor Pattern) 6 | 表示一个作用于某对象结构中的各元素的操作。 7 | 它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 8 | 9 | 包含五个角色 10 | [AbstractElement][抽象元素] 11 | 定义一个 Accept 操作,以一个 Visitor 为参数。 12 | [ConcreteElement][具体元素] 13 | 实现 Accept 操作。 14 | [AbstractVisitor][抽象访问者] 15 | 为 ConcreteElement 的每一个类声明的一个 Visit 操作。 16 | [ConcreteVisitor][具体访问者] 17 | 实现每一个由 AbstractVisitor 声明的操作。 18 | 每个操作实现算法的一部分。 19 | [ObjectStructure][对象结构] 20 | 能够枚举元素,可以提供一个高层的接口以允许 Visitor 访问它的元素。 21 | 22 | 访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。 23 | 为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式。 24 | 25 | 优点 26 | 使得增加新的访问操作变得更加简单。 27 | 能够使得用户在不修改现有类层次结构的情况下,定义新的操作。 28 | 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散搞一个个的元素类中。 29 | 30 | 缺点 31 | 增加新的元素类很困难。 32 | 在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作, 33 | 并在每一个具体访问者类中增加相应的具体操作,违背了“开闭原则”的要求。 34 | 破坏封装。 35 | 当采用访问者模式的时候,就会打破组合类的封装。 36 | 比较难理解。 37 | 据说是最难的设计模式。 38 | 39 | 适用情况 40 | 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 41 | 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。 42 | """ 43 | 44 | class Website(object): 45 | """ 46 | 抽象元素 47 | """ 48 | def accept(self, visitor): 49 | pass 50 | 51 | class Baidu(Website): 52 | """ 53 | 具体元素 54 | """ 55 | def accept(self, visitor): 56 | return visitor.visit_baidu() 57 | 58 | class Google(Website): 59 | """ 60 | 具体元素 61 | """ 62 | def accept(self, visitor): 63 | return visitor.visit_google() 64 | 65 | class AbstractVisitor(object): 66 | """ 67 | 抽象访问者 68 | """ 69 | def visit_baidu(self): 70 | pass 71 | def visit_google(self): 72 | pass 73 | 74 | class Visitor_Chinese(object): 75 | """ 76 | 具体访问者 77 | """ 78 | def visit_baidu(self): 79 | print '%s visit_baidu, [chinese advertisement]' % self.__class__.__name__ 80 | def visit_google(self): 81 | print '%s visit_google, [chinese information]' % self.__class__.__name__ 82 | 83 | class Visitor_American(object): 84 | """ 85 | 具体访问者 86 | """ 87 | def visit_baidu(self): 88 | print '%s visit_baidu, [american advertisement]' % self.__class__.__name__ 89 | def visit_google(self): 90 | print '%s visit_google, [american information]' % self.__class__.__name__ 91 | 92 | class ObjectStructure(object): 93 | """ 94 | 对象结构 95 | """ 96 | def __init__(self): 97 | self.website_list = [] 98 | def add(self, website): 99 | self.website_list.append(website) 100 | def display(self, visitor): 101 | for website in self.website_list: 102 | website.accept(visitor) 103 | 104 | 105 | os = ObjectStructure() 106 | baidu = Baidu() 107 | google = Google() 108 | os.add(baidu) 109 | os.add(google) 110 | 111 | visitor_chinese = Visitor_Chinese() 112 | os.display(visitor_chinese) 113 | # Visitor_Chinese visit_baidu, [chinese advertisement] 114 | # Visitor_Chinese visit_google, [chinese information] 115 | 116 | visitor_american = Visitor_American() 117 | os.display(visitor_american) 118 | # Visitor_American visit_baidu, [american advertisement] 119 | # Visitor_American visit_google, [american information] 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # design_pattern 2 | 3 | ### Python语言编写的24种设计模式 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 | --------------------------------------------------------------------------------