From 39c3d4621e815eba30a91d227e130ffa9d3abf17 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Sun, 4 Jan 2015 17:11:20 +0800 Subject: [PATCH 01/25] add observer pattern doc --- BehavioralPatterns/Observer/README.md | 63 ++++++++++ BehavioralPatterns/Observer/observer.py | 108 ++++++++++++++++++ .../Observer/res/ChangeManager.png | Bin 0 -> 30056 bytes .../Observer/res/ObserverBasicStructure.png | Bin 0 -> 17481 bytes .../Observer/res/ObserverCollaboration.png | Bin 0 -> 7688 bytes 5 files changed, 171 insertions(+) create mode 100644 BehavioralPatterns/Observer/README.md create mode 100644 BehavioralPatterns/Observer/observer.py create mode 100644 BehavioralPatterns/Observer/res/ChangeManager.png create mode 100644 BehavioralPatterns/Observer/res/ObserverBasicStructure.png create mode 100644 BehavioralPatterns/Observer/res/ObserverCollaboration.png diff --git a/BehavioralPatterns/Observer/README.md b/BehavioralPatterns/Observer/README.md new file mode 100644 index 000000000..c63a2cbe8 --- /dev/null +++ b/BehavioralPatterns/Observer/README.md @@ -0,0 +1,63 @@ +# 观察者模式 Observer + +## 意图 +在对象间建立了一对多的依赖,当一个对象状态变化,会通知所有依赖对象并自动更新。 + +观察者模式也被成为依赖(Dependents)或发布订阅模式。 + +## 适用范围 + +1. 系统抽象包括两部分,其中之一依赖另外一部分; +2. 一个对象变化会使得其他对象变化,而且你事先不知道会有多少对象会需要变化; +3. 一个对象能够在事先不用知道其他依赖对象的情况下通知他们,这些对象是松耦合的。 + + +## 结构 + +![structure](./res/ObserverBasicStructure.png) + +## 运作流程 + +以下流程图描述了1个Subject和2个Observer之间的协作 + +![collaboration](./res/ObserverCollaboration.png) + +## 模式效果 + +1. Subject和Observer之间的松耦合; +2. 能够支持广播通信; +3. 会出现“预期之外的更新”情况; + +## 具体实现时的一些Issue +1. 建立Subjects和Observers的映射 + + 关联Subject和Observers最直接的方法是在Subject中存储Observers的索引。但是,当有大量Subject和少量Observers时这种作法的存储消耗过大。一个解决的方法是建立统一Subject-Observer的映射,这样没有Observer的Subjectjiiu不会占用额外空间。 +2. 观察多个Subject + + 一个Observer可能观察多个Subject,单纯适用Update无法知道是那个Subject发生了变化,需要在Update带上Subject信息。 +3. 由谁负责调用Notify? + + * 在State的Set方法中调用。好处是用户可以不用关心这一过程;缺点是每次Set都会Notify,效率低。 + * 由用户负责选择调用时机。好处是效率更高;缺点是用户可能忘记调用。 + +4. 已删除的Subject的游弋引用 + + Subject删除时会在Observer里残留游弋引用,解决方法是当Subject删除时进行Notify,让Observer能够删除引用 +5. 确保State的一致性 +6. 避免适用 push 和 pull 模型 + + * push模型:把所有的变更信息全部发送给Observer,不管是不是需要;这一模型假设了Subject知道Observer的需求,复用性变差; + * pull模型:只发送一个变更通知,具体的变更内容需要Observer自行获取;这一模型强调了Subject对于Observer一无所知,效率偏低 + * 那到底该如何取舍? + +7. 按需发布 + + 在attach时添加interest信息,notify时根据interest进行,有的放矢。 +8. 当结构较为复杂时,可添加中间件`ChangeManager` + + ![changemanager](./res/ChangeManager.png) + +9. 合并Subject和Observer + + 一个对象很可能既是Subject也是Observer,在缺少多重继承的语言中就需要将这两个类合并,作为一个Observer基类进行使用。 + diff --git a/BehavioralPatterns/Observer/observer.py b/BehavioralPatterns/Observer/observer.py new file mode 100644 index 000000000..4ce1aed65 --- /dev/null +++ b/BehavioralPatterns/Observer/observer.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://code.activestate.com/recipes/131499-observer-pattern/""" + + +class Subject(object): + + def __init__(self): + self._observers = [] + + def attach(self, observer): + if observer not in self._observers: + self._observers.append(observer) + + def detach(self, observer): + try: + self._observers.remove(observer) + except ValueError: + pass + + def notify(self, modifier=None): + for observer in self._observers: + if modifier != observer: + observer.update(self) + + +# Example usage +class Data(Subject): + + def __init__(self, name=''): + Subject.__init__(self) + self.name = name + self._data = 0 + + @property + def data(self): + return self._data + + @data.setter + def data(self, value): + self._data = value + self.notify() + + +class HexViewer: + + def update(self, subject): + print('HexViewer: Subject %s has data 0x%x' % + (subject.name, subject.data)) + + +class DecimalViewer: + + def update(self, subject): + print('DecimalViewer: Subject %s has data %d' % + (subject.name, subject.data)) + + +# Example usage... +def main(): + data1 = Data('Data 1') + data2 = Data('Data 2') + view1 = DecimalViewer() + view2 = HexViewer() + data1.attach(view1) + data1.attach(view2) + data2.attach(view2) + data2.attach(view1) + + print("Setting Data 1 = 10") + data1.data = 10 + print("Setting Data 2 = 15") + data2.data = 15 + print("Setting Data 1 = 3") + data1.data = 3 + print("Setting Data 2 = 5") + data2.data = 5 + print("Detach HexViewer from data1 and data2.") + data1.detach(view2) + data2.detach(view2) + print("Setting Data 1 = 10") + data1.data = 10 + print("Setting Data 2 = 15") + data2.data = 15 + + +if __name__ == '__main__': + main() + +### OUTPUT ### +# Setting Data 1 = 10 +# DecimalViewer: Subject Data 1 has data 10 +# HexViewer: Subject Data 1 has data 0xa +# Setting Data 2 = 15 +# HexViewer: Subject Data 2 has data 0xf +# DecimalViewer: Subject Data 2 has data 15 +# Setting Data 1 = 3 +# DecimalViewer: Subject Data 1 has data 3 +# HexViewer: Subject Data 1 has data 0x3 +# Setting Data 2 = 5 +# HexViewer: Subject Data 2 has data 0x5 +# DecimalViewer: Subject Data 2 has data 5 +# Detach HexViewer from data1 and data2. +# Setting Data 1 = 10 +# DecimalViewer: Subject Data 1 has data 10 +# Setting Data 2 = 15 +# DecimalViewer: Subject Data 2 has data 15 diff --git a/BehavioralPatterns/Observer/res/ChangeManager.png b/BehavioralPatterns/Observer/res/ChangeManager.png new file mode 100644 index 0000000000000000000000000000000000000000..6b1ff0c942311f2d56dae5be41868b45dbaf1ec5 GIT binary patch literal 30056 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 literal 0 HcmV?d00001 diff --git a/BehavioralPatterns/Observer/res/ObserverBasicStructure.png b/BehavioralPatterns/Observer/res/ObserverBasicStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..07ee607496997d1c934a1502cab8948871ee5979 GIT binary patch literal 17481 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 Date: Wed, 7 Jan 2015 16:54:25 +0800 Subject: [PATCH 02/25] add abstract factory pattern --- BehavioralPatterns/Observer/README.md | 2 +- CreationalPatterns/AbstractFactory/README.md | 41 ++++++++ .../AbstractFactory/abstract_factory.py | 92 ++++++++++++++++++ .../res/AbstractFactoryBasicStructure.png | Bin 0 -> 20217 bytes 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 CreationalPatterns/AbstractFactory/README.md create mode 100644 CreationalPatterns/AbstractFactory/abstract_factory.py create mode 100644 CreationalPatterns/AbstractFactory/res/AbstractFactoryBasicStructure.png diff --git a/BehavioralPatterns/Observer/README.md b/BehavioralPatterns/Observer/README.md index c63a2cbe8..f26a5d087 100644 --- a/BehavioralPatterns/Observer/README.md +++ b/BehavioralPatterns/Observer/README.md @@ -28,7 +28,7 @@ 2. 能够支持广播通信; 3. 会出现“预期之外的更新”情况; -## 具体实现时的一些Issue +## 实现细节 1. 建立Subjects和Observers的映射 关联Subject和Observers最直接的方法是在Subject中存储Observers的索引。但是,当有大量Subject和少量Observers时这种作法的存储消耗过大。一个解决的方法是建立统一Subject-Observer的映射,这样没有Observer的Subjectjiiu不会占用额外空间。 diff --git a/CreationalPatterns/AbstractFactory/README.md b/CreationalPatterns/AbstractFactory/README.md new file mode 100644 index 000000000..4b96a7764 --- /dev/null +++ b/CreationalPatterns/AbstractFactory/README.md @@ -0,0 +1,41 @@ +# 抽象工厂模式 Abstract Factory + +## 意图 +提供接口,用于创建一族对象,而无需指定具体的类。 + +抽象工厂也被称为工具箱(Kit)。 + +## 概念说明:产品家族 +要理解抽象工厂,首先要理解产品等级(或者称为产品线)及产品家族(Famiy)的概念。一系列类似的产品属于同一产品线(或产品等级),而一套产品组成了一个产品家族。 + +以MonsterHunter中的装备举例,全套装备的产品家族就应该包括以下产品线:头盔、胸甲、臂甲、裙甲、腿甲,每个产品线会有多个产品,比如头盔有野猪王头盔、轰龙头盔,胸甲也有野猪王胸甲、轰龙胸甲。每个套装就是一个产品家族。 + +## 适用性 +1. 系统不必关心产品是如何创建、组合和表现的; +2. 系统每次使用多个产品家族中的一个; +3. 产品家族中的产品总是打包使用,这个限制需要强调; +4. 你想要提供一类产品,但只提供接口而不是具体实现; + +## 结构 + +![structure](./res/AbstractFactoryBasicStructure.png) + +## 运作流程 +* 通畅,具体工厂在运行时创建,每个具体工厂中有产品创建的具体实现,为了创建不同的产品对象,需要使用不同的具体工厂; +* 抽象工厂将产品的创建交给其具体工厂处理; + +## 模式效果 +* 使用抽象类隔离具体类; +* 能够比较容易地按家族替换产品;也能够方便地添加一族产品; +* 确保产品的一致性,一个家族的产品一并使用; +* 对于添加产品线较为困难; + +## 实现细节 +1. 将工厂创建为单例(Singleton),因为通常每种工厂只需要一个实例; +2. 抽象工厂只提供接口声明,具体的创建由具体工厂实现。通常,为每个产品线定义一个工厂方法。(工厂方法的详细描述见相关章节); +3. 定义扩展工厂。添加一个产品线对于抽象工厂会比较麻烦,需要修改所有依赖的类,一个可行的方法是工厂只提供一个`Make`方法,该方法接收一个参数,从而决定创建的具体对象。 + +## 其他 +抽象工厂的核心就是产品家族、产品线的创建,根据“开放-封闭”原则,抽象工厂是对产品家族的扩展开放、对产品线的扩展封闭的一种设计模式。 + +正如抽象工厂的适用场景的描述,当我们有多个产品家族、存在每次使用其中一个完整的家族的约束,这时候抽象工厂模式可能就是我们想要的。 diff --git a/CreationalPatterns/AbstractFactory/abstract_factory.py b/CreationalPatterns/AbstractFactory/abstract_factory.py new file mode 100644 index 000000000..a32c067e6 --- /dev/null +++ b/CreationalPatterns/AbstractFactory/abstract_factory.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ + +"""Implementation of the abstract factory pattern""" + +import random + +class PetShop: + + """A pet shop""" + + def __init__(self, animal_factory=None): + """pet_factory is our abstract factory. We can set it at will.""" + + self.pet_factory = animal_factory + + def show_pet(self): + """Creates and shows a pet using the abstract factory""" + + pet = self.pet_factory.get_pet() + print("We have a lovely {}".format(pet)) + print("It says {}".format(pet.speak())) + print("We also have {}".format(self.pet_factory.get_food())) + + +# Stuff that our factory makes + +class Dog: + + def speak(self): + return "woof" + + def __str__(self): + return "Dog" + + +class Cat: + + def speak(self): + return "meow" + + def __str__(self): + return "Cat" + + +# Factory classes + +class DogFactory: + + def get_pet(self): + return Dog() + + def get_food(self): + return "dog food" + + +class CatFactory: + + def get_pet(self): + return Cat() + + def get_food(self): + return "cat food" + +# Create the proper family +def get_factory(): + """Let's be dynamic!""" + return random.choice([DogFactory, CatFactory])() + + +# Show pets with various factories +if __name__ == "__main__": + for i in range(3): + shop = PetShop(get_factory()) + shop.show_pet() + print("=" * 20) + +### OUTPUT ### +# We have a lovely Dog +# It says woof +# We also have dog food +# ==================== +# We have a lovely Dog +# It says woof +# We also have dog food +# ==================== +# We have a lovely Cat +# It says meow +# We also have cat food +# ==================== diff --git a/CreationalPatterns/AbstractFactory/res/AbstractFactoryBasicStructure.png b/CreationalPatterns/AbstractFactory/res/AbstractFactoryBasicStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..934b6b6bd74f3a03a3132ea131248615ed02656f GIT binary patch literal 20217 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 literal 0 HcmV?d00001 From 25484fb58d133907ed4193fd08c811d8e8ceb649 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Wed, 14 Jan 2015 17:52:34 +0800 Subject: [PATCH 03/25] add adapter pattern --- StructuralPatterns/Adapter/README.md | 89 +++++++++++++++++ StructuralPatterns/Adapter/adapter.py | 93 ++++++++++++++++++ .../Adapter/res/AdapterComposite.png | Bin 0 -> 9970 bytes .../Adapter/res/AdapterInherit.png | Bin 0 -> 9437 bytes .../Adapter/res/PluggableAdapter1.png | Bin 0 -> 12851 bytes .../Adapter/res/PluggableAdapter2.png | Bin 0 -> 16684 bytes .../Adapter/res/TwoWayAdapter.png | Bin 0 -> 17077 bytes 7 files changed, 182 insertions(+) create mode 100644 StructuralPatterns/Adapter/README.md create mode 100644 StructuralPatterns/Adapter/adapter.py create mode 100644 StructuralPatterns/Adapter/res/AdapterComposite.png create mode 100644 StructuralPatterns/Adapter/res/AdapterInherit.png create mode 100644 StructuralPatterns/Adapter/res/PluggableAdapter1.png create mode 100644 StructuralPatterns/Adapter/res/PluggableAdapter2.png create mode 100644 StructuralPatterns/Adapter/res/TwoWayAdapter.png diff --git a/StructuralPatterns/Adapter/README.md b/StructuralPatterns/Adapter/README.md new file mode 100644 index 000000000..139d119e8 --- /dev/null +++ b/StructuralPatterns/Adapter/README.md @@ -0,0 +1,89 @@ +# 适配器模式 Adapter + +## 意图 +将一个类的接口转换成用户期望的接口形式。适配器使得原本因为接口不兼容而无法协同工作的类能够被正常调用。 + +适配器模式也被成为封装器、包装器(Wrapper) + +## 适用性 + +适配器模式非常容易理解,它的适用场合也很容易想到: + +1. 想要适用一个已经存在的类,但接口却不是我们想要的; +2. 创建了一个希望那个被复用的类,该类需要和未知的、目前不相关的类兼容; +3. 需要适用已经存在的多个子类,但去一一适配这些子类的接口不现实,此时就需要一个`对象适配器`来适配基类的接口 + +## 结构 +适配器有两种实现方式:继承或组合: + +1. 继承 + + 适配器继承操作对象和适配目标。这类适配器成为***类适配器***(***Class Adapter***)。 + + ![structure](./res/AdapterInherit.png) + +2. 组合 + + 适配器继承操作对象,并持有适配目标的引用。这类适配器成为***对象适配器***(***object adapter***). + + ![structure](./res/AdapterComposite.png) + +## 模式效果 +类适配器和对象适配器各有优劣。 + +类适配器: + +* 由于类适配器继承了适配者,这使得该适配器对其子类不起作用; +* 由于是继承关系,适配器能够重载适配者的方法; +* 只增加了一个对象,而无需额外的指针或引用; + +对象适配器: + +* 不但是适配者,连其子类也能被适配器调用; +* 难以重载适配者的行为,有时候需要添加一个额外的子类给适配器调用,从而达成预期; + +使用适配器时,需要考虑以下一些因素: + +1. 适配器需要做多少适配工作?这主要取决于目标接口和适配者接口之间的相似程度。 +2. 插件适配器:类中内置的接口适配器,称为插件适配器,使用时能够使用几个适配器中的一个。 +3. 使用双向适配器来提供透明度。被适配的对象不再兼容Adaptee的接口,因此并不是所有Adaptee可以被使用的地方适配器都可以被使用。双向适配器提供了这样的透明性。在两个不同的客户需要用不同的方式查看同一个对象时,双向适配器尤其有用。 + +## 双向适配器 +网上看来的一个例子,解释了双向适配器的概念。 + +假设有一群狼和一群羊,其中有一只狼W和一张羊S由于某些狗血的原因成为了好朋友,狼想请羊去家里玩,羊也想请狼去家里玩,但两个族群是天敌,不可能友好相处。 + +他们想了一个办法,做一张神奇的披风,一侧是羊皮,一侧是狼皮,羊S披上就可以伪装成狼,狼W披上另一面就可以伪装成羊。有了这张披风,两个小伙伴又能快乐地玩耍了。 + +在这里,这张神奇的披风就是一个双向适配器,经过它的适配,羊可以适配成狼,狼可以适配成羊。 + +![structure](./res/TwoWayAdapter.png) + +## 实现 +1. 适配器的C++实现:适配器公有继承Target,私有继承适配对象,这样适配器就是Target的一个子类,而不会是被适配对象的子类。 +2. 插件适配器的实现: + * 使用抽象方法的插件适配器 + + ![structure](./res/PluggableAdapter1.png) + + TreeDisplay的使用方法: + + GetChildren(n); + for each chile { + AddGraphicNode(CreateGraphicNode(child)); + BuildTree(child); + } + DirectoryTreeDisplay适配了文件系统的方法,使之能够显示目录结构。 + + * 使用代理的插件适配器 + + ![structure](./res/PluggableAdapter2.png) + + TreeDisplay的使用方法: + + delegate->GetChildren(this, n); + for each chile { + AddGraphicNode(delegate->CreateGraphicNode(this, child)); + BuildTree(child); + } + 委托这一形式在Objective-C中使用的非常频繁,也非常实用。TreeDisplay中包含一个delegate对象,该对象可以根据不同的需求进行切换。 \ No newline at end of file diff --git a/StructuralPatterns/Adapter/adapter.py b/StructuralPatterns/Adapter/adapter.py new file mode 100644 index 000000000..1620ce4c4 --- /dev/null +++ b/StructuralPatterns/Adapter/adapter.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://ginstrom.com/scribbles/2008/11/06/generic-adapter-class-in-python/""" + +import os + +class Dog(object): + def __init__(self): + self.name = "Dog" + def bark(self): + return "woof!" + +class Cat(object): + def __init__(self): + self.name = "Cat" + def meow(self): + return "meow!" + +class Human(object): + def __init__(self): + self.name = "Human" + def speak(self): + return "'hello'" + + +class Car(object): + def __init__(self): + self.name = "Car" + def make_noise(self, octane_level): + return "vroom{0}".format("!" * octane_level) + + +class Adapter(object): + + """ + Adapts an object by replacing methods. + Usage: + dog = Dog + dog = Adapter(dog, dict(make_noise=dog.bark)) + + >>> objects = [] + >>> dog = Dog() + >>> objects.append(Adapter(dog, dict(make_noise=dog.bark))) + >>> cat = Cat() + >>> objects.append(Adapter(cat, dict(make_noise=cat.meow))) + >>> human = Human() + >>> objects.append(Adapter(human, dict(make_noise=human.speak))) + >>> car = Car() + >>> car_noise = lambda: car.make_noise(3) + >>> objects.append(Adapter(car, dict(make_noise=car_noise))) + + >>> for obj in objects: + ... print('A {} goes {}'.format(obj.name, obj.make_noise())) + A Dog goes woof! + A Cat goes meow! + A Human goes 'hello' + A Car goes vroom!!! + """ + + def __init__(self, obj, adapted_methods): + """We set the adapted methods in the object's dict""" + self.obj = obj + self.__dict__.update(adapted_methods) + + def __getattr__(self, attr): + """All non-adapted calls are passed to the object""" + return getattr(self.obj, attr) + + +def main(): + objects = [] + dog = Dog() + objects.append(Adapter(dog, dict(make_noise=dog.bark))) + cat = Cat() + objects.append(Adapter(cat, dict(make_noise=cat.meow))) + human = Human() + objects.append(Adapter(human, dict(make_noise=human.speak))) + car = Car() + objects.append(Adapter(car, dict(make_noise=lambda: car.make_noise(3)))) + + for obj in objects: + print("A {0} goes {1}".format(obj.name, obj.make_noise())) + + +if __name__ == "__main__": + main() + +### OUTPUT ### +# A Dog goes woof! +# A Cat goes meow! +# A Human goes 'hello' +# A Car goes vroom!!! diff --git a/StructuralPatterns/Adapter/res/AdapterComposite.png b/StructuralPatterns/Adapter/res/AdapterComposite.png new file mode 100644 index 0000000000000000000000000000000000000000..623ee51d167333d25c90e927d71f28d7a33b79e6 GIT binary patch literal 9970 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

bN+--$~e#eoUS(O{M}S`IxiJ` zzN^*2v%g_e5j^Zr&%dsq+3pzy+UCd{>zrojSimY**PK@-YI^65NY{bpw@Pc9>O>wI`x36?%bpERAlg=Q4SER6&PII|JikS!z zCOY}N!hIZLAw|Z~spv;fW>|D&JdYdfV0s?LE8y#TP5)?!F;3&QuQ7i6xC_eDb*`7P zia(=$$)nWX4esY!k`}Yd&uEp0qj8f}#pce2$C&6sSh?F|*SWTTe{`GSipvAF@vrG= za}5ZqOjm(S%0@nR8^n%oTT%3x(^)rTTXW;gYk>q`c0fOv& zfzICVt6`aPMuaR5_1FFd*1zi==_liF4aeTL<7ymA?T!Ju%x3cd-mL1p7)lcjO2@gf zrNF+aTv_jyvMBJSw3=_Zc%d3tdv>wIGl0)~LH~00PbZ{~`||N);IU%n4ay}K)u&-z zYeJ@ldkU2JTo~r2EcLIR{9Gz!>!sDJ%Dnf1qP?%Yx>{WpIbkr}!~8PJomvb)cdx27is^&c+`1Rb@rBO_Jhsp}uGf6V80$ zKz2$50>4+4hPQt9jFI?vy(HVlO6SEaZ#_vl`5#TmTA;`ySqtjHPzjnhtKe^B(Q_gc zaYebw@K>|_jeHvbh^!Eai2Z-h5dPv44z8H-SIhtao#QEw;vM+1-?*$l<=PTJOI`P2 J*@NeA{|!a1FcJU& literal 0 HcmV?d00001 diff --git a/StructuralPatterns/Adapter/res/PluggableAdapter1.png b/StructuralPatterns/Adapter/res/PluggableAdapter1.png new file mode 100644 index 0000000000000000000000000000000000000000..8beaba766da902bb105802fe2a1cde892bcb2caa GIT binary patch literal 12851 zcmdtJRa9KxwSc{Ogh&7Yph|rLDFFanC+tW2`UNZk z$}_zNfOmitNJPao?Fizb6KAp_bUOB^S7XzRldc@M&b=8@$Nf4xCMEP+XrZeXmN20Ve38#fZjNS{FjePmm&yK2;Yp9-zb= zc-}kWd5dvngOURRWiy9kVuW-ue+E&0?&~x+`~_mY#|qeO#R-(Y48U{VS$pMy5jbmS zVT2bdFL5wZFr!V9nf51kg1UE?E<>MuAM4nMlb5bYv`npJ2EnlZ)9&c*f=TF9P`j8$ z((WCtpeFW}u8V9aOI%?EGl>LPGsoUGZ)Ay*VL?|q_AVjPVt^dHkmFo9vA&)&Qk#^7 z38cN|x_jf)s(p{7$j&UljIv51Xmg7p;o~~BjL3wN_^Go?`#SqgHo;TOX{VaU2UtWR ziWD+o=MQ@X6UI|h@fD6goFPIlQ>|uhdD!^)J_8oRE4#XJr^&0iBe^A&X!g%jO400t zGGWOd_P|K=t;ZLR2 zOQxVGtJvospHXc5R-1AaSH*b_OuWmqQEFf2g_Ud`1-ThgpMP+aNVc-zpaNbaU&6oh zndmX73{71XNlNi~^%WW^8XHF5r9YKFB-!l3#E`!9n?J5_j0Hnti>Ya?ITeT5-aC(Z znP*TuQP-lWqNz{~S(bnXNw&c$?d{^R&K!risl)xLOTM;@?3?jJ4WDe z7w;5HW)f0g!ZPHsf<{$Ghib0P{Y-2lA(F-eBE*G_Pj

I|OBT8|{V}0$N;hG>`o| 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 Date: Thu, 15 Jan 2015 17:10:14 +0800 Subject: [PATCH 04/25] add composite pattern --- StructuralPatterns/Composite/README.md | 94 +++++ StructuralPatterns/Composite/composite.py | 340 ++++++++++++++++++ .../Composite/res/CompositeStructure.png | Bin 0 -> 15942 bytes .../Composite/res/TypicalComposite.png | Bin 0 -> 8380 bytes 4 files changed, 434 insertions(+) create mode 100644 StructuralPatterns/Composite/README.md create mode 100644 StructuralPatterns/Composite/composite.py create mode 100644 StructuralPatterns/Composite/res/CompositeStructure.png create mode 100644 StructuralPatterns/Composite/res/TypicalComposite.png diff --git a/StructuralPatterns/Composite/README.md b/StructuralPatterns/Composite/README.md new file mode 100644 index 000000000..38a90ac73 --- /dev/null +++ b/StructuralPatterns/Composite/README.md @@ -0,0 +1,94 @@ +# 组合模式 Composite +## 意图 +将对象以树形结构组合成一个整体,表现出部分-整体这一层级结构。组合模式使得用户能够像使用对象一样使用这个组合。 + +组合模式在日常绘图软件的使用中经常会用到。例如先绘制了几个图形,然后将这些图形选中,将它们“组合”起来,之后就能像使用单个图形那样,拖拽、缩放、连线这些操作都能使用。 + +## 适用性 +1. 希望表达对象之间“部分-整体”的层级结构; +2. 希望用户能够忽略单个对象和对象组合之间的差异,一视同仁地进行操作; + +## 结构 + +![structure](./res/CompositeStructure.png) + +一个典型的组合模式结构一般如下: + +![structure](./res/TypicalComposite.png) + +用户使用抽象基类Component的接口,如果实际对象是Leaf,则直接操作,如果对象是Composite,则依次执行其中的Component操作。 + +## 使用效果 +1. 定义了由简单对象和组合对象组成了层级结构,简单对象能够组成更为复杂的对象,复杂对象也能用于继续组合。能够处理简单对象的用户代码,也能处理复杂对象; +2. 让客户代码更简洁。客户代码能够统一处理组合对象和单个对象,无需对其分类处理; +3. 能够很容易地添加新的组件,客户代码可保持不变; +4. 缺点是会限制你的设计,因为要让每个组件都极度统一。有时候你希望某些组合中只包括组件集的一个子集,此时就需要一些运行时检验了。 + +## 实现 +1. 在Component基类中添加显示的父节点的引用 + + 有利于层级关系的处理。父节点引用的设置和消除尽量写在`Add`和`Remove`方法中,而不要开放给用户使用; + +2. 共享组件。 + + 两个组合中有同一个对象,这两个组合可以共享这一对象,这有时候非常有用,比如减少存储空间需求,但在子节点中记录多个父节点会比较困难。这一话题在**蝇量模式**再深入讨论。 +3. 最大化组件接口。 + + 为了能让客户代码方便地调用接口,当然希望组件基类有尽可能完备的接口提供。但这样又会让Leaf对象中出现大量的方法根本没有实现。 +4. 子类管理方法的声明 + + Composite实现了Add和Remove方法,但这两个方法该在那里声明呢?是Component基类,还是Composite基类? + + 这是一个安全性和透明度的权衡: + + * 在所有类结构的基类Component中定义管理接口提供了透明度,使用户能够对所有对象一视同仁;但这么做缺乏安全性,因为用户可能会在Leaf中调用Add、Remove方法; + * 在Composite基类中定义管理接口能够提供安全性,但这样的话Leaf和Composite就有了不同的接口,缺少透明度,用户就必须知道当前对象的基本类型; + + 从OO开发来看,透明度应该更为重要一些,为了弥补安全性问题,可以有以下方法可以参考: + + class Composite + + class Component { + public: + // ... + virtual Composite *GetComposite() { return 0; } + } + + class Composite : public Component { + public: + void Add(Component *); + // ... + virtual Composite *GetComposite() { return this; } + } + + class Leaf : public Component { + public: + // ... + } + + // ... + if (test = aComponent->GetComposite()) { + test->Add(new Leaf); + } + +5. 该不该在Component中添加子类列表? + + 同样是处于透明度考虑,那是否该这么做?这样做最大的缺点是浪费空间,只有在仅有较少Leaf的系统中这么做。 + +6. 子对象的排序 + + 可能会有Composite中的Component排序的需求,例如绘图程序中,每个Component就是以图层的前后作为排序依据。如果确实有这样的需求,就要在实现时考虑这个问题。 + +7. 通过缓存提高性能 + + 如果Composite经常会被查询或遍历,就有为其缓存的必要。当修改了其中一个Leaf时,这一缓存就需要被更新,所以显示指向父节点的引用此时就显得各位重要。 + +8. 生命周期管理 + + 子对象的生命周期尤其父对象管理,即由Composite负责删除其中的Leaf或子Composite。 + + 但是,当Leaf对象是不可变且共享的,就不符合这一原则。 + +9. 该使用何种数据结构来存储对象? + + 链表、树、数组、哈希表这些都可以,效率优先。事实上有时甚至不需要使用数据结构,Composite中的Component是一个“萝卜一个坑”预先定义好了的。 \ No newline at end of file diff --git a/StructuralPatterns/Composite/composite.py b/StructuralPatterns/Composite/composite.py new file mode 100644 index 000000000..9b8cc56fa --- /dev/null +++ b/StructuralPatterns/Composite/composite.py @@ -0,0 +1,340 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +A class which defines a composite object which can store +hieararchical dictionaries with names. + +This class is same as a hiearchical dictionary, but it +provides methods to add/access/modify children by name, +like a Composite. + +Created Anand B Pillai + +""" +__author__ = "Anand B Pillai" +__maintainer__ = "Anand B Pillai" +__version__ = "0.2" + + +def normalize(val): + """ Normalize a string so that it can be used as an attribute + to a Python object """ + + if val.find('-') != -1: + val = val.replace('-', '_') + + return val + + +def denormalize(val): + """ De-normalize a string """ + + if val.find('_') != -1: + val = val.replace('_', '-') + + return val + + +class SpecialDict(dict): + + """ A dictionary type which allows direct attribute + access to its keys """ + + def __getattr__(self, name): + + if name in self.__dict__: + return self.__dict__[name] + elif name in self: + return self.get(name) + else: + # Check for denormalized name + name = denormalize(name) + if name in self: + return self.get(name) + else: + raise AttributeError('no attribute named %s' % name) + + def __setattr__(self, name, value): + + if name in self.__dict__: + self.__dict__[name] = value + elif name in self: + self[name] = value + else: + # Check for denormalized name + name2 = denormalize(name) + if name2 in self: + self[name2] = value + else: + # New attribute + self[name] = value + + +class CompositeDict(SpecialDict): + + """ A class which works like a hierarchical dictionary. + This class is based on the Composite design-pattern """ + + ID = 0 + + def __init__(self, name=''): + + if name: + self._name = name + else: + self._name = ''.join(('id#', str(self.__class__.ID))) + self.__class__.ID += 1 + + self._children = [] + # Link back to father + self._father = None + self[self._name] = SpecialDict() + + def __getattr__(self, name): + + if name in self.__dict__: + return self.__dict__[name] + elif name in self: + return self.get(name) + else: + # Check for denormalized name + name = denormalize(name) + if name in self: + return self.get(name) + else: + # Look in children list + child = self.findChild(name) + if child: + return child + else: + attr = getattr(self[self._name], name) + if attr: + return attr + + raise AttributeError('no attribute named %s' % name) + + def isRoot(self): + """ Return whether I am a root component or not """ + + # If I don't have a parent, I am root + return not self._father + + def isLeaf(self): + """ Return whether I am a leaf component or not """ + + # I am a leaf if I have no children + return not self._children + + def getName(self): + """ Return the name of this ConfigInfo object """ + + return self._name + + def getIndex(self, child): + """ Return the index of the child ConfigInfo object 'child' """ + + if child in self._children: + return self._children.index(child) + else: + return -1 + + def getDict(self): + """ Return the contained dictionary """ + + return self[self._name] + + def getProperty(self, child, key): + """ Return the value for the property for child + 'child' with key 'key' """ + + # First get the child's dictionary + childDict = self.getInfoDict(child) + if childDict: + return childDict.get(key, None) + + def setProperty(self, child, key, value): + """ Set the value for the property 'key' for + the child 'child' to 'value' """ + + # First get the child's dictionary + childDict = self.getInfoDict(child) + if childDict: + childDict[key] = value + + def getChildren(self): + """ Return the list of immediate children of this object """ + + return self._children + + def getAllChildren(self): + """ Return the list of all children of this object """ + + l = [] + for child in self._children: + l.append(child) + l.extend(child.getAllChildren()) + + return l + + def getChild(self, name): + """ Return the immediate child object with the given name """ + + for child in self._children: + if child.getName() == name: + return child + + def findChild(self, name): + """ Return the child with the given name from the tree """ + + # Note - this returns the first child of the given name + # any other children with similar names down the tree + # is not considered. + + for child in self.getAllChildren(): + if child.getName() == name: + return child + + def findChildren(self, name): + """ Return a list of children with the given name from the tree """ + + # Note: this returns a list of all the children of a given + # name, irrespective of the depth of look-up. + + children = [] + + for child in self.getAllChildren(): + if child.getName() == name: + children.append(child) + + return children + + def getPropertyDict(self): + """ Return the property dictionary """ + + d = self.getChild('__properties') + if d: + return d.getDict() + else: + return {} + + def getParent(self): + """ Return the person who created me """ + + return self._father + + def __setChildDict(self, child): + """ Private method to set the dictionary of the child + object 'child' in the internal dictionary """ + + d = self[self._name] + d[child.getName()] = child.getDict() + + def setParent(self, father): + """ Set the parent object of myself """ + + # This should be ideally called only once + # by the father when creating the child :-) + # though it is possible to change parenthood + # when a new child is adopted in the place + # of an existing one - in that case the existing + # child is orphaned - see addChild and addChild2 + # methods ! + self._father = father + + def setName(self, name): + """ Set the name of this ConfigInfo object to 'name' """ + + self._name = name + + def setDict(self, d): + """ Set the contained dictionary """ + + self[self._name] = d.copy() + + def setAttribute(self, name, value): + """ Set a name value pair in the contained dictionary """ + + self[self._name][name] = value + + def getAttribute(self, name): + """ Return value of an attribute from the contained dictionary """ + + return self[self._name][name] + + def addChild(self, name, force=False): + """ Add a new child 'child' with the name 'name'. + If the optional flag 'force' is set to True, the + child object is overwritten if it is already there. + + This function returns the child object, whether + new or existing """ + + if type(name) != str: + raise ValueError('Argument should be a string!') + + child = self.getChild(name) + if child: + # print('Child %s present!' % name) + # Replace it if force==True + if force: + index = self.getIndex(child) + if index != -1: + child = self.__class__(name) + self._children[index] = child + child.setParent(self) + + self.__setChildDict(child) + return child + else: + child = self.__class__(name) + child.setParent(self) + + self._children.append(child) + self.__setChildDict(child) + + return child + + def addChild2(self, child): + """ Add the child object 'child'. If it is already present, + it is overwritten by default """ + + currChild = self.getChild(child.getName()) + if currChild: + index = self.getIndex(currChild) + if index != -1: + self._children[index] = child + child.setParent(self) + # Unset the existing child's parent + currChild.setParent(None) + del currChild + + self.__setChildDict(child) + else: + child.setParent(self) + self._children.append(child) + self.__setChildDict(child) + + +if __name__ == "__main__": + window = CompositeDict('Window') + frame = window.addChild('Frame') + tfield = frame.addChild('Text Field') + tfield.setAttribute('size', '20') + + btn = frame.addChild('Button1') + btn.setAttribute('label', 'Submit') + + btn = frame.addChild('Button2') + btn.setAttribute('label', 'Browse') + + # print(window) + # print(window.Frame) + # print(window.Frame.Button1) + # print(window.Frame.Button2) + print(window.Frame.Button1.label) + print(window.Frame.Button2.label) + +### OUTPUT ### +# Submit +# Browse diff --git a/StructuralPatterns/Composite/res/CompositeStructure.png b/StructuralPatterns/Composite/res/CompositeStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..d588b984591fcdb43a8f37ee0eaa9dcb4a1f751d GIT binary patch literal 15942 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 U5qPEG{%}C@ove7#8(qKu1)e)SQUCw| literal 0 HcmV?d00001 diff --git a/StructuralPatterns/Composite/res/TypicalComposite.png b/StructuralPatterns/Composite/res/TypicalComposite.png new file mode 100644 index 0000000000000000000000000000000000000000..8cf28aad1e61e559d43598e3ac94ab1335d65009 GIT binary patch literal 8380 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 F{{=30#25eo literal 0 HcmV?d00001 From 4ab3bb9b002944302721c7838c85046b94afd0ee Mon Sep 17 00:00:00 2001 From: luchengchao Date: Mon, 19 Jan 2015 16:30:08 +0800 Subject: [PATCH 05/25] add decorator pattern --- BehavioralPatterns/Observer/README.md | 3 + StructuralPatterns/Adapter/README.md | 5 ++ StructuralPatterns/Composite/README.md | 1 + StructuralPatterns/Decorator/README.md | 65 ++++++++++++++++++ StructuralPatterns/Decorator/decorator.py | 31 +++++++++ .../Decorator/res/DecoratorStructure.png | Bin 0 -> 17062 bytes 6 files changed, 105 insertions(+) create mode 100644 StructuralPatterns/Decorator/README.md create mode 100644 StructuralPatterns/Decorator/decorator.py create mode 100644 StructuralPatterns/Decorator/res/DecoratorStructure.png diff --git a/BehavioralPatterns/Observer/README.md b/BehavioralPatterns/Observer/README.md index f26a5d087..d9f936382 100644 --- a/BehavioralPatterns/Observer/README.md +++ b/BehavioralPatterns/Observer/README.md @@ -5,6 +5,9 @@ 观察者模式也被成为依赖(Dependents)或发布订阅模式。 +## 经典场景 +订报纸 + ## 适用范围 1. 系统抽象包括两部分,其中之一依赖另外一部分; diff --git a/StructuralPatterns/Adapter/README.md b/StructuralPatterns/Adapter/README.md index 139d119e8..159899a20 100644 --- a/StructuralPatterns/Adapter/README.md +++ b/StructuralPatterns/Adapter/README.md @@ -5,6 +5,11 @@ 适配器模式也被成为封装器、包装器(Wrapper) +## 经典场景 +1. 欧版插座和亚版插座的适配; +2. Objective-C中的Delegate的使用; + + ## 适用性 适配器模式非常容易理解,它的适用场合也很容易想到: diff --git a/StructuralPatterns/Composite/README.md b/StructuralPatterns/Composite/README.md index 38a90ac73..6d0108c15 100644 --- a/StructuralPatterns/Composite/README.md +++ b/StructuralPatterns/Composite/README.md @@ -2,6 +2,7 @@ ## 意图 将对象以树形结构组合成一个整体,表现出部分-整体这一层级结构。组合模式使得用户能够像使用对象一样使用这个组合。 +## 经典场景 组合模式在日常绘图软件的使用中经常会用到。例如先绘制了几个图形,然后将这些图形选中,将它们“组合”起来,之后就能像使用单个图形那样,拖拽、缩放、连线这些操作都能使用。 ## 适用性 diff --git a/StructuralPatterns/Decorator/README.md b/StructuralPatterns/Decorator/README.md new file mode 100644 index 000000000..a35aa310f --- /dev/null +++ b/StructuralPatterns/Decorator/README.md @@ -0,0 +1,65 @@ +# 装饰器模式 Decorator +## 意图 +动态地向对象添加额外的功能。装饰器提供了扩展对象功能的选择。 + +静态添加功能,第一时间想到的就是继承,但动态地、只针对对象个体地添加功能的需求,就是装饰器所擅长的。 + +## 经典场景 +装饰器有一个非常经典的咖啡的范例,有机会将这一场景引入,能够更好地说明。 + +## 适用性 +* 动态地、透明地向单个对象添加功能(或者说职责),而不会影响同类型的对象; +* 添加的职责能够被收回; +* 想要添加功能,但是使用子类继承的方法是不切实际的,例如添加大量独立的扩展会影响大量代码,或者某个类不可见,无法进行继承; + * 例如结构中描述的,ConcreteComponent类文件不可见,只能访问到其基类Component的场景。 + +## 结构 + +![structure](./res/DecoratorStructure.png) + +## 模式效果 +装饰器模式至少有两个有点、两点不足: + +1. 相比与静态的继承更为灵活 + + 装饰器能够在运行时为对象添加职责。 + 另一方面,装饰器允许为对象多次添加职责。以奶茶为例,可提供的奶茶类型有原味奶茶(奶茶基类)、半糖、全糖、多糖这么四种甜度的,价格也不一。如果使用继承,就需要有三个子类,但是如果使用装饰器,每被封装一次就是加半糖,不同类型的奶茶只是装饰次数的差异。 + +2. 避免在架构层级中创建囊括过多特性的类 + + 装饰器实现了需要时附加功能的特性,而不是在设计时就要充满远见地设计完备而复杂的类,对象不用在囊括许多本身根本用不到的特性。 + + 如果需要扩展特性,实现也非常方便。 + +3. 装饰器和对象本身并不一致 + + 装饰器和对象的外特性一致,但本质上并非同一事物,当需要用到对象的ID时会发生错误。 + +4. 大量的小对象 + + 使用装饰器注定了会产生大量相似的小对象,虽然系统知道谁是谁,但是代码Review、调试时会比较困难。 + +## 实现 +1. 接口一致性 + + 装饰器的接口和对象的接口必须一致!因此两者都是继承自同一基类。 + +2. 省略装饰器的抽象类 + + 如果只需要添加一个职责,那就不要定义什么抽象类了,直接使用装饰器基类进行装饰得了。 + +3. 保持Component基类轻量化 + + Component基类中只定义接口,不定义具体成员,这样创建的装饰器也是轻量化的,否则大量的复杂的装饰器使用起来就不那么简洁轻量了。 + +4. “治标” vs “治本” + + 装饰器是在原有行为上添加一层,可以认为是一种“治标”,另一种选择是改变对象的内部机制,称为“治标”,例如使用策略模式。此处的“治标”与“治本”并无绝对的优劣之分,不同场景下有不同的擅场。 + + 当Component是一个重量级对象,策略模式是一个更好的选择。Component将其某个行为交给独立的策略对象,策略模式能够在不同的策略对象间切换行为。关于策略模式,在相关章节中再做展开。 + + 由于装饰器模式在外部修改Component行为,Component本身对装饰器一无所知,所以装饰器对于行为是透明的。 + + 而对于策略模式,Component知道可能的扩展,会持有相应策略的引用。 + + \ No newline at end of file diff --git a/StructuralPatterns/Decorator/decorator.py b/StructuralPatterns/Decorator/decorator.py new file mode 100644 index 000000000..ce96f3153 --- /dev/null +++ b/StructuralPatterns/Decorator/decorator.py @@ -0,0 +1,31 @@ +"""https://docs.python.org/2/library/functools.html#functools.wraps""" +"""https://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python/739665#739665""" + +from functools import wraps + + +def makebold(fn): + @wraps(fn) + def wrapped(): + return "" + fn() + "" + return wrapped + + +def makeitalic(fn): + @wraps(fn) + def wrapped(): + return "" + fn() + "" + return wrapped + + +@makebold +@makeitalic +def hello(): + """a decorated hello world""" + return "hello world" + +if __name__ == '__main__': + print('result:{} name:{} doc:{}'.format(hello(), hello.__name__, hello.__doc__)) + +### OUTPUT ### +# result:hello world name:hello doc:a decorated hello world diff --git a/StructuralPatterns/Decorator/res/DecoratorStructure.png b/StructuralPatterns/Decorator/res/DecoratorStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..1e88524622197725044da8c97d01e43ffb34fd67 GIT binary patch literal 17062 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 Date: Tue, 20 Jan 2015 11:20:15 +0800 Subject: [PATCH 06/25] add factory method pattern --- CreationalPatterns/FactoryMethod/README.md | 119 ++++++++++++++++++ .../FactoryMethod/factory_method.py | 45 +++++++ .../res/FactoryMethodStructure.png | Bin 0 -> 11698 bytes .../FactoryMethod/res/ParallelHierarchies.png | Bin 0 -> 17908 bytes 4 files changed, 164 insertions(+) create mode 100644 CreationalPatterns/FactoryMethod/README.md create mode 100644 CreationalPatterns/FactoryMethod/factory_method.py create mode 100644 CreationalPatterns/FactoryMethod/res/FactoryMethodStructure.png create mode 100644 CreationalPatterns/FactoryMethod/res/ParallelHierarchies.png diff --git a/CreationalPatterns/FactoryMethod/README.md b/CreationalPatterns/FactoryMethod/README.md new file mode 100644 index 000000000..7669ce1d5 --- /dev/null +++ b/CreationalPatterns/FactoryMethod/README.md @@ -0,0 +1,119 @@ +# 工厂方法模式 Factory method + +## 意图 +定义一个创建对象的接口,由子类决定具体实例化的类型。工厂方法让类的实例化推迟到子类中进行。 + +## 适用性 +* 一个类无法参与该类所必须创建对象的创建过程(只能下放给子类参与); +* 一个类希望由子类决定创建对象的类型; +* 一个类将创建对象的责任委托给了几个子类,而不必去关心这些委托具体是如何实现的。 + +## 题外话 +提到工厂方法,很容易联想到抽象工厂,但从两种方法的适用范围来看,着重点是有差异的。 + +抽象工厂着眼于产品家族、产品线,强调每个具体工厂有一个完整的产品家族;工厂方法更注重对象的创建责任委托,即由子类去考虑究竟该创建什么对象,怎么创建对象。 + +## 结构 + +![structure](./res/FactoryMethodStructure.png) + +Creator依赖其子类定义工厂方法,返回合适的具体对象。 + +## 模式效果 + +工厂方法去除了代码对于特定应用类的依赖,代码只和Product的接口打交道,因此能和用户定义的所有具体Product交互。 + +一个潜在的缺点是用户必须实现Creator的子类、仅仅是为了实现工厂方法。 + +还有两个额外的效果: + +1. 为子类提供钩子 + + 将对象创建的过程封装在工厂方法总比直接创建对象更为灵活。当对象版本有扩展时,工厂方法为子类提供了现成的钩子。 + +2. 连接平行的类层次 + + 这个概念比较抽象,需要一个实例辅助理解。 + + 假设有个图形对象,用户可对其进行拉伸、移动等操作。考虑到图形类型多样,实现这类交互并不容易,有些属性是与图形描绘相关,表示的是图形的性质,有些属性与操作相关,不同的图形可能会有不同的属性,相当的操作会有不同的实现方法。 + + 考虑到以上一些限制,一个合理的设计是将图形以及其操作分离,但每种特定的图形又有其对应的特定操作。其结构图如下: + + ![structure](./res/ParallelHierarchies.png) + +## 实现 + +当实现工厂方法模式时考虑以下问题: + +1. 两种主要的形式 + + * Creator是抽象类,无法实例化对象,使用时必须定义子类并定义工厂方法; + * Creator有默认的工厂方法,只有在要重新实现工厂方法、创建非默认的对象时定义子类并定义工厂方法; + +2. 参数化的工厂方法 + + 又称为**简单工厂**([维基百科词条](http://zh.wikipedia.org/wiki/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95#.E7.AE.80.E5.8D.95.E5.B7.A5.E5.8E.82)中是这么命名的)。 + + 工厂方法传入ProductId,根据ProductId决定创建的具体对象。这样做就不必要复杂的继承逻辑了。当然,也可以使用子类重新实现该参数化的工厂方法。 + + 一般的参数化工厂代码形式如下: + + class Creator { + public: + virtual Product *Create(ProductId); + } + + Product *Creator::Create (ProductId id) { + if (id == MINE) return new MyProduct; + if (id == YOURS) return new YourProduct; + // repeat for remaining products + + return 0; + } + + // subclass of Creator + class DerivedCreator: public Creator { + public: + virtual Product *Create(ProductId); + } + + Product *DerivedCreator::Create(ProductId id) { + id (id == THEIRS) return new TheirProduct; + + return Creator::Create(id); + } + +3. 语言相关的一些特性 + + 具体语言具体分析 + +4. 使用模板来避免继承 + + 想要使用工厂方法,就必须创建相应子类定义具体的工厂方法。在C++中另一种方案是使用模板来避免这种情况: + + class Creator { + public: + virtual Product *CreateProduct() = 0; + } + + // template creator + template + class StandardCreator : public Creator { + public: + virtual Product *CreateProduct(); + } + + template + Product *StandardCreator::CreateProduct () { + return new TheProduct; + } + + // sample + StandardCreator myCreator; + Product *product = myCreator.CreateProduct(); + +5. 命名规则 + + 给工厂方法以特定的命名规则,使得用户能够一目了然,例如: + + Class *doMakeClass(); \ No newline at end of file diff --git a/CreationalPatterns/FactoryMethod/factory_method.py b/CreationalPatterns/FactoryMethod/factory_method.py new file mode 100644 index 000000000..c21e3960b --- /dev/null +++ b/CreationalPatterns/FactoryMethod/factory_method.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/""" + + +class GreekGetter: + + """A simple localizer a la gettext""" + + def __init__(self): + self.trans = dict(dog="σκύλος", cat="γάτα") + + def get(self, msgid): + """We'll punt if we don't have a translation""" + try: + return self.trans[msgid] + except KeyError: + return str(msgid) + + +class EnglishGetter: + + """Simply echoes the msg ids""" + + def get(self, msgid): + return str(msgid) + + +def get_localizer(language="English"): + """The factory method""" + languages = dict(English=EnglishGetter, Greek=GreekGetter) + return languages[language]() + +# Create our localizers +e, g = get_localizer(language="English"), get_localizer(language="Greek") +# Localize some text +for msgid in "dog parrot cat bear".split(): + print(e.get(msgid), g.get(msgid)) + +### OUTPUT ### +# dog σκύλος +# parrot parrot +# cat γάτα +# bear bear diff --git a/CreationalPatterns/FactoryMethod/res/FactoryMethodStructure.png b/CreationalPatterns/FactoryMethod/res/FactoryMethodStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..48eb75ad53168de6db5d2e845672976fc91ecee6 GIT binary patch literal 11698 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­0+jISsk-oyE@l*+=VH-fvCXaLpKQz6ZZ zG$U68!NN(HyFU-eUyF`^lH43MAS|M)1DE+%SaP1Nm#FvJG#in2%pe;tR?`wBfb{(O zIqP=+YU(1C&X=8f0Ni38aBIzY%kFo#&zYT;8ZdQii(hw<+}+&9(}L72bTg-WaFzJ& zx3m@$tZU839@wlWy%y<)JydV2uIPVr1OEAO)Nq(ZKO!q27o3tTO)Ch2EX+8_Gm}@b zUXaZza^N6Y9F?l^=G7oV{HJqpyr%#lPUU*5*D8p2D{Bs7(= zJ&u_ftxRQzXXV}_{m40IK&4et71QnPX&G5TF9xW(GB>$DGzds|6XJQp_$f6LVr{!*(CgWb0--SgaUB_fX4kEEYLP#m9+=W7_e z?q2Z#zCyzWSvcMO&_Eg-o{z#JlHSzvM5Y4J(Q_(Gm^vTpsn=G_%j`0|OkjSxBM{(o zx&dW4nUf9$1co75OeVUP+S;I;`Vs-p3_oG=?r`|9oq{D z^dg5JAJVwOqp`@=*B32Ek&Bh*^?&^IaIi1Y(ob^3hNN{)0R*ynSa8{cbb#MlN5?`Q zc88_StX2D-^;nz^GE`@GN%3iD`pSj+cG|`i<_6e+JHBuUzF-$`nPNh=a{N*g6n= zOmSX5WE36x0dfHEosp|#?)v9;y()2+^-N?HAG}v{0D_`Du6T4{U;L0`E+lrG8YSSv z%g*ok>SpuOF08h&D215nSFq!CT_-Nma;=A%Vg^&W+k$W;KYM(IZmk>RkiX=3NTYR! z5g&>R^_~|XHGED+yoQOCGeEKU+VCs(oUPgmAuJMUwbDEkI^UkGA2!kYi~7;P$eA<; zwB{2y>V30^@^&CG536PBrNtbJkH=J!LKkPZpXZ0fSh_^5?+9T4X`;FV8z**0z!C}h z28qf60kwk6{pekI#0WdIn|=3JTwGQfPWSFFZIa=*=xBiijLKmzIOrLze%j z&f||TI6_`@<9oZ$tse%!Me5G?<&$9gsa?e~UUS9yw}%Z>>dTgju4)o$GnUPgI3`6! zx{FMcmZHVhm#HAz)w(N8D8N7QoK4$0_>DiSebXrRJ-$iYknyNmZ_#)!uVr92QziUR zsp%yojrB5DI|yQdm>%JK zsQ58t#zFjM3anu@`#?dS4>`8DcekJ~I2pD#*J7cKCdo%Hz-alK1*TDVgP#TT-oxL} z?wAZTnd@uE{@n0A*dNNoj8~;Z*=xf^=RpfJdVcgz|q&pTd z7sawfHA*-*J3N7SpA?sDU_Wm&>QO8XmZO-Ik1rzOFrW0rhQ9>;T1q55MqLZJ@f+qV z)8?$Y9Z}gI*X*|pxVseSvZ!rjq%STZzCN$|{YEIB>!z_rtt;z1FKQR$X&~=wC30u% zX?rnsNkNYIqKW8;6Z=U?A7HE`esq4#Oa7&2N$9bwDxxz8o}i#I^((U*Kiykgkoj4Y zn&kN?88As-=g`n%@dI@cYjqSB^ojRXRn2W4i73bBa_)&Wr}j)6h1Bl+s?ed=T zr*P4%)`v>KE=;H9C@jte%TX(+`nc%{UE}d&w0mmsj9B6>cx@LF^*z?HH≻So*qh zy6<56DRG(K)|D6_`;5UEo-VjDF-#3�%b^m6P001h02f!$ba)!GNmT4zIg#&+FYr zptXOm-^PVUD2uLghol5+w5i_fSM^@8dwKh&uklvW_Dnmcc;1vo_zv`ifO$J0(8$0n ztRUvbdp;jMy=SohH7ZR|{Q6WM0jzZ2CaQdD*IFYnW3Qwa662d=TE>YW~>xt+%rZanTyi6avB+v+`9tPG8@=NDw?2z@ikyaU1}P= z84sDXwT_vea%!fO)OBkFt(MW)ZT;ajjryVvJB7J6_7&yv2K90Y%ba*f%bQh9Dspg` zJ`q+E@t}RmaIU=DqGuN5V|4-+Rc*tsqI8UKE@>TRc)kzKgp;~%kLYAJ!mJBw34VuZ z*$x{Rt_W@7SwR?8X&5Y>XtCr4$=O)QOyjvIk+W>5ky%b&WrVDfkh=CU%WM+0u)k!7 zZ~U(P3zo(34EAE0jc};W1Xr#giDi~x^qq{}@~bmk$l;dd!u;GpMhs3wDMXC;0GdwUvUqAM&N8Eo5TN9eZpJjt5y{#G}J6HJE~DH?Lq9KBYd5 zyG?D#W&M#2oQ&gj1Cnt8kuxXAg%ug{D7S}eF}|n0(_PT3P4Ab5Na$DCfq?8rgnyQC z{^Lpee@MIkHR1j*@c93~3DFUl`_WRA@+GA#OPN#>*^@JJC-O%p5sR*AKG+8d(>Z%E8_!qm?je7oD^WhN>PClwF ze+)KIK`^oV5_c$gJU1aUByzL`uzr25A=$(Pymys7*KKcyG#>A0pxOly0UQv@bHvRx zK2(aQ=}2TorNTg8sSs+$=hY_HGAI(p)X3h>0!e!{7NQG_wG7GhWj$1&skIsPqldLz z%|u|L=hK4SQ+&7mmD-+ya@voWXW1nqfun;E4gNEgUJ9Yq_IxN{!tTB0fYd4(g?CU` zO6@U<9SzGyDMQElYqCU=Y=`aw-*cS1lc+ahn>Adb1gj=MbETppDjHVD+nc5hnko5^XxjG-cFG)uKgR={!ci%J2>oN zRK;&AK<ViX*%AVwKaxTycasmRLG8CXu_HD17uw6K`(5vm?^-o@7m*6?&?nOyCQ2hm|CYZlP14hKI_!s9+xfph5O!x9yOy%n#rxG zLXldWHkP+rKHe2$BHHI}wh(tuIU2yjV3W*ju4$YLCiu48&aNJLUtq7uFS4|doZjxL z)jq4Vyel9n$Db6n6voK_?Qy`#!oBfB@08KKtAauR5HXAiV?*W_t~#pbRVD7XoOK(C zAt)3u{H7l9-Vy#jAAHIIg!$%g`&;^tdTaRYU}OOlU}u9*pIQikK-i$QA6F>fzJ@rw z_Cse+OFg-gmNcK7$mqUFAO+aDSIT$7v06ugi{DBSN$EvFSyO@h>F*JN3xk<8%TeD4 zCq%$7r4EW!#PuvKG1eIwcsFU5?$L^knH~otobl;x8Td#T#ZceNI;E+JZ!t4=0dXY6lw51_u*IpNIz9Pb*^BVhf~3y||&qYptGuFRqqP4JX# zB(N6I#{s&F>kBcQ?I$er0V4j(M@a3$*Yk`@>pJ`wU0P2qI|(PykUc}n==L7ao!SSM z+U%;lDT`*7-`K1+z6RhBlr!?$pgK}lN8?&6%CBt=qmu2^SXwWwH?CK?p3a}s+@#-# z9~_(%m$x@)>`LrtJiQ+{5>UDwI8CTIRq&nkzQ$QzZRe?DgTvZ4GY#h@4HG*Y*z9b$ zQgVm!lUQc@sEl+x^_o2E=weYywe8{$vRGK?$>1A+kp@4}@2D`s5|n zYX8aTWa%VI3-GBtUYuT+*qE)CHQqrL2!ua3Nbq9;#F*V3KRgsa-&TiX_Q_*h{aCuV zf5t!eQY7;WNtRI#f`LPV64c~{f-SR`0L3&E#3N8l(%Bj`RD616!lGZmI)*E>5mXKU z`tL6y3{be$wQEn~j~}+DRl1}&4#KNR@{uD#JWPR<8hFvWYDA0)& z8XP=OJnf^;XULB5BHU+OFmc&`4L-oc{5_C|iTrz@{h0dq!0a(8TmI=s=)apM^vfTS z*^j5KI1o$4=Y_Z;hpmG<7vs~=Aj-Xu$f9W_a!`ob_)%z!_61n)W=@d2lzTxjQk1%% z!-6e<_X3iQ2kFC_Ph{@woaE#*2t))6&QLUC`)p#c_|-8GcXDB}XIxl5trcV(jDluH z18M3o3ce~&jA9Rf9g&ChUUZ`!vc%mS46H9M%+d`*>%Ao+cS+$Fq^i zkiv22ge9$nvWfn9RpCyPU_VuFS0-|4?c#nNuh2@#PyMt?PLp<-SWkdQ0BH@X3yp|0 z?(5sB>C69X2ru`)gYYp`E{;rk3N&tiB!GhdQ95qrmBDp}|4!EGaeD_Am5y@vP%RqS zGbJ|Gx*B>X5P2tah*?&(p+ba$o=cBYRJ%$(t*Bjp=qF=#$HWCvjAgDb5-Tb?nE&eG z@bk)g-~W5j$Y{lMq|$=^+)>j!Vej4UR<84)JsWV=5Sf)4o62q2!3uepQ#C@n2;35H zuc(F1Odz0@^|1tR)%&&?6v2Jfrd73Go1Ua{esrk==cHS5>tVDy%UUwR_qZurxwkj0 zs5=Sj>}YtMzd>?rOr)Rp-{~`hOc`elK2qs?5^IsefZBb15DQ(IOuTDlJTKIYRGBp= zu8obPQsOe&&=H+?+9TPY=zST6uS36^-o5qCk@VJzVk4VvY1Y@tN2(KQ611K7$bBcw z*r%)V$Av$#a0G&{Q_j*-jDzZ+02Hdkd`HpHXgPbE!l5#}Lr%&yLz?)7I-{m523;-f zctV<#B7RM+eCO;+TG46KgWuCLqwaIDhwsAWMveR9mPW({LlC{UtwvfGqwmKmWp`X9 z-qzLF*8gfrA&F|7G#g%?LQl+h2B5olIQ5xefZd|w@FZfxBKJ$g@7s)boz=-Mt1uH) z_o-dr^JcS@22?;Ump#Vd7j-+X79*1MaWRO+(`2Pea+}F>uV|v;-jgfm?umcKHNsT! z{&p`fMByF=7lZFY`-ro++Oja%ySB@N(4EV7vAHWWJg)jQd2DuL{{h5CV$cFU?Jb^N z1`P2+e5#K@UmoMiPWkMnv^3@%10a>;-G3rpaLsb7Hu@Db8uP;?q>#)PSLt1}LAI$t z1B#8?uaz2;50uD%9^e(_>yvhOrvex`W0fFP=Y{!G;XF1rH8mS6g|W#~mBXpVH^ZUu z!y${DqWOhf;yzAYzvY>=`vZAYODCPLraO#-n}~&2rf?wXH)Ih-5sq}}=hk8xD)Kib z5qa_&mw0YX0p=YV((2MpDV>$^FTTFou)7G?CGaCw3_QQB~r0}mVd+_AcECLHqYExi0D)&v5k>V15R*3xOx zTXPq#(I51+<1qvsX95}(fP%IS--=yB?iDM_k8EAHZ29KXkfxE0!uIjA_&Mk>e-B6H$?Rj~jQcpk`J(2TIdBR3A|b$s zn7_KpVYSB{?MIvofLvcN`8uiE9d zrjlgNyScRB9(Fn^ta%T_OvyxT#57FMJfg+}z(QZ&)>I!%N5wpj^^T|9;yO2dfwU(M zkoW2is-pt_9KSp+b8CbKDkNrf6cM%jvF43y`6@z6#ygN#A?cTi6mcP`1!q8R!ISF{ zAze@erDJuR&C;FKixF50iCn*~8J*x0YXogI7j1m1Uuw0-_FYlg z#StO~u;uRX0KfjBo8EO=Bxk#<6hC=g_po+&kEUi;|Ap&4j|HibL?FaoL?HpKG8G?# zy-_?hLWhpE{WbXOw_;x(^QCb=h-W?v^@X;010=S$=iL&7c@ti@yPWPQ=rL>Snc_bT zs_h`r@8?4xvij5;=VFmVyYj1Ljc%yXz4! znTm(eCS^9=Y8hcnho+$Hc0HKS>iDcXa4KT9m=wzg;q@5dKwP^A*rCLb$rJqdS&%I6EkG`chG(&+Jl4BngEW2Z*Z9J$4c7-e!4^MeQrUvak#Z! zWY|xJJt@8^`fwnm~LnDbX6+g5Cia$71Rx4l)6S1|45ZuKeS=mj(%EtLz zCCgd|fhuGh4wToFU9dVYnjuDRAJj}mu)LAC6sPb!p1@<=G4^P*2C-P zJ0gPpmEXPJZ4fnyRUs=N=fS!Byj^r~k7wIIaQB?Iq`w65ancIv?`R^ZFJpNbE^pFk zqhfT&uBDekcABLpp3qVS?}wMS+})4KdGcUMZb-@V*PWQ7Vm``$VUTv5tn5GV@I*oz zj&R3Be)o5)!T&+?;s27Z;AGH{SCL)DHZ{R-vc7P*LpK^iFqZra4*IY98e2{nm?1v) z%z&J`2ZEzGQwXylWGqF8OiA*O^6`X6nRfBRtn zVR6WBUHG=cOB zv|5|@n__xUp(0!{25^oVh!H|3ltA7Hr3ULaFzh!jXh5qI<&81{l5jmk1IO?^POKDW zLz{&N5Ag~FQva=2a^a=bKmgoI_&ReF1nT+nZ^!0_neZf&k|0%$q1A#F2K9Kl)vC%L zkIiLbXY(Y-8P$ZECyZbX37Nc8JzP7V17mSOCJB8gR1Is|gjt1p0WQ@@+vpCp=*;7A z{R%3br&Fwa@78fZ$)jZbA|akJej=~v%%vuT%r}oyHJ4(HY9eEnI6W< z`|&F*f!T4EgN@z7bGT0??(}EnEb2&;i`;A@i}w4#P0;IU?nv0d6Ma5WmnO3cDi<4l zi_7IFwd>UlWvfe;=Q6Y_h-gen0bcu9*#bsZggVPljfE(X&S}Y#)SBhKWxgyJb#BadU;w%2Ml8&O(a zKhtru+PF(3h+C69ExLJ2$TJST%t%7EHCXzpdkctp5vJ2a^rCc2j5%0O?$Q)m_Q4(Ml3#ymWm;a99-Wlk$s zlX3>MwqYbnhvpsm0{LUDI+JZ-sBGV7T)sASmdIiy(yUYpnM~2_;1Z%h!{f8*_{L+( zwSvetZj5Xh8RPIyhTnjMwL!<2<4|f{R;PwP5aU#K%@0%qHR|! zL^9*MxD?loIXu$XU8o}hfm}rT>~TP#vOnYXf5UNaW0UeVWnk;jXq`7vnR_&3j zBF9inbs;GT6n(n}_dk#0JU91D3R_w@ChmEwyg-BYG>HOR9W6)#Ti+hx3ConXJeIP(0QD-(tE!U?J zKXwO`8c5L!N_xm2uMuhOa6&9tzbGUY&FkiVg$nX2P>LFd+^ya9f78p207bVo9InMr zdhX#xL?(;_=kMXtI+TVeEvkwIyiWdk7RW2XuR+-7?awKg%3oQOFL?06Dig2=6B=0MA%;-az&5BgE6Vjg4 z&9RphoJP_sk7)NM6jdd1Hh-YhA1pc2wQl9{ie)kB^Y>yrKlh5$1D~}Vkbg&zn5#s%uF~5T))dgWPo5oiOe9YMiNNz!b8r+0&l-|j|p=Ep=`30uX}M!0LIH|yYIbO#)r5v(5CvRwB$s*3N~wm^0~jK*UY zhIj9li5PE5gycD|Zq1$U%SGt2Y*O>C$7A=6fS0JV)Bjl7>_*p zW2@wD4Qyy<7eVMkV@Dv^l(VP@&OligZJ}yTvtH$F58aM(6t{i|T@EM4ZVib6|M+$v^JD&(p#7rK@1T2^!3+n)!P4YE&5zL4YX$Y<@Wz*gLW`O#Y~fvO2}OvxU*#n- z)~>zlDAQ;BN9}?h^RqH=He#KT;$qJNH?BSYWvcSBf!m}TEpq`|g!AF5!V~K#(yI@c zVy@5!_byZxwa1UesieKY2(qJ=@)Ex2AW?tTqB8BVTuXD<8qiYo2?s>6r*?2k7cxOxQTS5+>=l(3UuP|Dz`o4@b z-ECZa-a^!1k#nzL9Sf$t0TZOd`DtkZw^KyBS+7F9=6SPtwJUjGmQeW&!-5`Wa+dKq zHT`j{2ewAPo#-gaZyZ>+wIl9*DHgWxw+S# z4>hoe%}A|kj4VAx&Z+Ix+JY3*z2Xo zM0WXe981@|@c57@viCaWGAHZ&@P!#+REoIJQbTxJXb zCUXKpY@KS#{28?iqa6VVVsNy=kH(z-`SUH23S{|u7iYdE=!teA#Hq6nw08qo%&2<9 z?5c0xd_8STEd&B_-~sOe$3A;kqFqItfgPLqw|sAR_gNBoE}(S>W43s+E?Xuz<9X4u znq3)US{*F}nu%goy8iW++@EJ|I{dXH6j!vi%5!*Tqh+6!QrH|A2J;SCSx=qUxHapm zzel@9je`QD5WIyXUEhtDdStTqU;yw)-Y38LZq*au+?@j=o^l^f{dN+9Q&Df?7ocBw zKVaUxwzO0}hxk%`I`@L-zWu&m$XuSlP>)xn^UD_J!yy`pL-h@Ktuu@uv?CasXzp22 z_7=AP)p_BVnIDaQ$hH^Xh!MSSJMohk&p|Pq@&bGL_NK|)RQ8nj{WaR5lZvrMw=GSd94PG+HG8a8z1{Q`X2SK!S6@yW@4gSx7U)p!r{gU?0ro}yRlMWWTqCwY|kdT!nW za*o<4`ISb6kTjKxdvpY%h0-D_>%7teLY6IBHyoU@M_`OX2pGC64hipwj*R(q|A3)e=SJFIE&t^`rTuJR zaEi)V-DMswnMEd5FjY@%z+PMOse2$MV@?=Ro^YSr9-$JB(1gaM2tBnnV!qB^4hG7 z%v{WtTgzF~>Js4FaI;rBQ%;K=u?j+F7PA7!P?b+dK?lu%Gwkfl{ruu48S}dk)-j&h zAZ+57_(4)~DdcfeRo0xfxnsf<|0-o#hNIKMi*uQTxvmt)!$v;+IkZs^top-HM1GL7 z{H5sDi3l{EnLLv2q<-y}_ElK*dO7XJQKT(%Vx#A(cutnsq>iY=m!kAIdQ4KE@RE{d z@4|Ox0wIPJG+*NneToO>bAcWQ4Kf&}wa$?_dqr43Sj%l};zb%_EiV`%vM9vYiy9Rx z$D(O+uu7ud3|m9Bn{lt~e`hX9IQl06nae*ojV@Q~WQjsn(l5nd>%GCtQ1uYtMFJptZ>yZN6VgD=*l;ye~IVM7+bY0n6>FY zt3pR~@ELZ_wzRW|M$T)Lwip_M4+1IG!l2J`R$sd!RbQNNv%G`Lzr^UxjZNXB*VDM@ z`e1gGs8MI_E5vNz9YhS;iVKx)bErgjWqH1eC`iC=R9+|^t3|tw7bme^e3DKo6^VeM(&-$Sg!o@^tHPfykE7pKd_1orFI411MrDU3O5St-QJIvluoAQLIgFD{DlYS(&%=y5 zUY3ohgHSCEY>CxGUxK7?O{u482$3~L?G+5meNeAeZD=y7hQL($PoURl37dK8;NAz4cW zbe1oDeqrylo2?UKp-d+mIAd9uTKoR?=8ZlmKeb`N0UoWXOL9^A;(^`L`{gGHqj07G z=8Wv$4PATRlUB;+of$TXM?1RO=u^}Bso51*V)}2qcpIEW#%yrf@$CZ`>*=#aY!1_2 zuuWqQj1zFC60ois^RjNMN3l-14jC@QXKT=bJ*;-2%8D<*Ef?e)b!_<-M}p7m_V)9b z`x=VGjCS^dNol}kFRrxU4j)xt%YDDhh|0~wJ)NZmS7DbMR|9T7tJnmrs~llV8zV-e z311fC$WE;ua@u3e83>9QWGZ45aJAd}W>Z69sY&328WS^D(Ny5HK79l}h&x(n5vNUX zx1UYZ;cjHliWLibC+l9jI0M79)LMF$wCNgTFL5aD@CW@=h7ug{JbWRx!ZEbcAu>nD zWVbiQl4Y+-YTLe5DD)8T0e8r|KO;I{ejnNy65;y7F1Rpu;aJ8_YqCvDPtsL)s51O! znx%i4(S2LT=CR9<<>+j$=p@<%?vM|oqr~wl%(ItD+DArd2!^SQAFQ|AZudb&5i@+{ z8$ML&O1aavko@=OFEObIB|30QFwxN0h0ENv zx#OmLd5&`d;|$VdL;~oVo~;m7!lxt!x*?-)F()27XEjCOO|c7N#hj-s8xwwB!(WPs z`@B3S*NOqo-D&_QzMH%Y~vyP&(5 z6zHEl|5M+#qx|+gQ|7{Hvk1Dq)*j{O%5ii#*4u55A(sXXC?x#F9cv*CUOM{sOnJFv zBUO-D&P-rYmTfrLc3IX|SnJ zaC~O4uMbsBB&8m4i0OU0yXpi(@9qpUH<1*n4XtygX&ilSk}Jf0`B06j^^icb&ucsw zTf(R6U^Dx%bvRLT9>!~^CbxOW`9>bS@-&6kzeYmx*-vQxDj2IOx z^r`yNHy~U69FzQFHukK!KxON9;T*oh-9qy_Adt};Al6KYMfIhW{fSvYAaAuFFc3&9 z*JG8ARa$yBDrT3vNIoyY^Y}!huZ1vCqkQp`2E*o;cA&_xZU$7L_*b#=JyGcw?*a{f zPyLmJYZdh~+G}TYU{KIYd+6dw>t>X!JXj;!@_eR{U5-Q$?ZY^p*!XnzX$|h{@h->% z8A|sil6xynKIHmat?|(m*A*orzh(y&prSMqDrCekXu5p}ACt@8esx%)-!*g;pRV*` z<>^XVQhYx-^|R)ViKkKgV)eD=PZqIC5$IY3W)jpaC5x=is26fs6>bKC8o-L&`~P zl+ww)h_X?e)umdsa4D1UefXE=!^)Z~&DFJoq>FQ&@PzQg-wRloN+9M`w=o+KDVe(L zO8eaDh1}mnRx)h0LJ20J%+qD2YnG5dzSDo>mjG&*w!q%Rqy-k z%Y>`&o%&XvkKg&{GOe@~eYSeqbw5vemP*3!-{<2|`O3<{lLOiA=&J7-Cf*H^h3XD1@JEW7jzmG_2LTU=`>A|l1LjkXuTO!mxJWPKkCjtTWxG(M|W;!#y@ZF|~H&3XuU zN_)*pY+`oDFX{x&O*ybc>pUn+u1*vAf{|8mvw5)VYqlu-ZKmka+cOM`zUOi-=vZCQ zx!xmTp7Ait>!LdmEj(eqvq97dbKzdi0S#olC8lH_`&P^$lS{kt>*kn5ie1fX28Tg% z(rF9k*+_*Mm%V$J`=3np^CjXpH?=PqsHeGV7Qz+2x2IYVm>vF=5H(SV>fBR)6B2q+ zO2;THYBT=1tCJBc!S40+^1Wn3vlpT*_s+1znVeuLmkNB8DF<>87#E%()l2~l`jk@j z0=&e2wGUng3NARS`singVg!8ms!w2-#JA+$jktMKzEx7+9358*W4;RtUBt zu?A+xO-+_b!P(5={IbE)9*n9v58uBa2}b=8x^1_r+A=Kei@ z|NW?yYlqA}qG^Zp_U$PDT#o)V;sSotmrco2=|yg`+?ncYdOj|&nqv~kWgUb(j~MRv zdJkLVu#a-W0}{{ILgxGR=~h6pRcii8rI6ESL)&n~l7?w8Vd2YMuZwXL98AEjp1gA| zGhNO87)>2emlJH5EOWhvBxXG`R&wjhW-QyHKVy0+EM}f^S?JiBzA|P=sWBen(KvLS zUr^p2HDGJJ(lGCnmT-+q)4QZS{*M3hJ-fq{%IN3mC@LHIxBg>SW~x(NQD2?_80rFgx=@ zB7(WtD3stM`xkM2(s;53z0>M(gbf~Xwu|}nTs$(N_51y;;z~A{=8kWVz-<&yBcPkw zlYA#W#QNg#0c6y(&XYoGv=M}fR6jWsT;rg(gpYv8_bdr1oX%53U0LL0iZZWDgJKQ0 zFo<_dRimgU34!~t0WeTAU(x~1F>&iUT7Hps%8yU;Er|I!(rGjObZcQh&6yC&)D~?b z(xqUe;Q6NduzIF-Wu@|a12Fnz!tdXQEEfvsZlLY-eUtLD!!X=6J1OCb$jYnYa`aAP z_*`V}QB!e}G#oQSp{k{rW(!Xr%FWfFfypSI7L++_nU-?9{ACwvyuU#>Fj@z|6x~Sc zy+N%QXaB5InOuRrFe8?IsyX=62kUPJ#z}PUKq|UCOO8kNNq{PQrBU6tZ zTfg4EGxbFQ$c5QWyJhi{E}Ki%xze=(7C`(4N^#o}#M@SbX zVGMQ#lBA)c?C8Mbh+I0xbZaCe5255@J?eg@cJ4{P&aq5IutL z`Vw<*RvDWt;c@m&zT~%C_pO3JAgC8=K1*vNb$X-6Tm^8d_uW*+N!!dXcZokzUmfEk z%5syu(wlvEz0YcdAJ=4kwkpY!&A(~CnSEAs-%e8bch$aZ%r8#Pu{u)7g=t$6)rn9Y zM}gaZcggdfenU~BK;NxcIkTP#&I%}VTM*^&sF0oIwZbl?-*cR`+)b})D`GIA;OFDo zlyl#)RN=2;O+*`R2wy>w!A^u6DTUFY4TjO7ln;;4(LdLyvnXl@3vYmgscYItfU>AV z6nS^up9@5P7t7Hlaq>P~Qj%f;#@d3zKnvdOdIL)QfCB_geZ_$e247Fn0^?>JsE980 zfSD#zpDlQfY9%J>fpePHZIA=;_2fs--%E>jYZgsrC8-*C7fXuQJ}h~ATe9wc@~}(u z%gn@L0u!D#)~|AWf?gxQCteF3d{vOWZcp<1ZRf>%!PJlm-13Jt?JR|pvitF3OIGE1 zAn#q@Em%);Z}R*-o)q#OChxw5DT>VtW((o#Hvv2C19y)@hxHGw_@+rH`6f7NuTyxPinklHbEK=SRxDtYO0qV9l(7DxDS_7CyVu)i-4O2eWC&e-rvLTUq?zuE&D1GqSVp) z<5|}!e$qLNKwVB;qX#5U0yLk06Sbx{60qCK)!vy*6+zYVoKfTCEO(4LnDQQ3_tqU9;u0gO?Z}gdUrW~w|IyB6!oYUgv zrFP#?wspRqRtWUwT~9jDmIw%gE^DiD{%jO9K8yJ!L?Ncb!lo?S;qR)UUb=7Fk40XU zx94oi)O^qDdpI>UrYCq80NlL&PdRd+uZNyzF+5~NZ}9MxjWj^1)pvnRCu{rjP4nb8?jSiF&12FD zyd3orlO@BRc1z`av-ws#ApqQ;Xm(*=0d>y$TE5N$;CXZvsVRu=f->^nx}R~?n-+00 zZ$#+G6^F|=7e@o8C~pq=vGhlAV{01h%Nd_Pvyyp-nFI!k7@hH`jVU%HU>gkQ-dp_! zz+3%d)#%^F#h)b^pWBCO6=XN4mpF&WZ@VFWtDI=WDk;EtoD=8V+U|-wdZvM+u=_ev z+ClCxv#GGv6ZUm1y3idv9vdjMJDk%X)%`TO+({z+sA&u`ZZbM+-FvFldWKM=o=<7ds{3E-)HR4)8sV-&uU8-8yyre@P~2ZLb}$?D22jX*)|2)H zdWtIeQQXD~X(jv?Z)f&C!jdK(jZVvjnl1V#nPfE^Ub|agoM!T#AD#-)9plxl#0t5% zwk*dLp(%gt8MWMwk`5$%{1*-QbIMI6RSTuWuc}oLq~opYX^B^vdFI}5+~dbiwsG^v zJ8>kr?<_@%ZXTQVwFz`lSLZZbwxi#5AGcKX6gumTJg0Rj?u+Lq+!vtz{J*gV&qkL`DXmmre~-*rf#@>z3+_u9gzqb zA*NyZCjJ;XF)XyQ4>9N5gh%YZ?qHgeo}BzfvMNc%vJO47ly(RC=+XJ9_x6R(t;%uZ zA)=Z7+n`y^mc8d%yt!92z$J_t{m4aQNBPJwWdyIc+MQda!VL1z_jH{=3 zOT1mE^$ct$JTS4HM>q*j->!hCR}fZ&;KI2pPd4q3D><<>Q+X%j*a}Vfs2L(D?;U(` zT(e7EpStJmCHzo^c#OPZaa_mCG$K7&N2lQ+4|7u^Nd4pS1{nZ>6JrnJhf_-+*fTp~ z0!wKx0+7oOxqFr7wy_Ap?h1mY5I@lY3V;()p~|u&T3+9(x4#(X)L{2p0D#M+M1}P( z)}Oy9`Vg2cF`KY9uDhmFGHN!u(B5cYb#gI2{6v$uCf{1vWH!|Z>nOYzOE!9$`{oJ6 z?F~<{DhvGv$}~!WGoDNrSdq3cbz>2Z9gWQ|1a=cjuAJBM=*B%GXd^75V;#P!-vUwn z${$CMB#b+J1g2)K0(brx=hcNd?19;Lt2C`U3K>MdmV#lcURQBu_pFWJSSn&xD#EnJ z+DHuXRvY@fj{xIke4&rmj;22BGHgHt!~pm0WLipac3!RePX2xKrWqXcUtz0UFroiG^+28Y=|>@HyE%ak@#<(0I&Q;uUt$ z%l>UYF>l%TR1GS|v+2*cKg*633NBiptyid>xF`t`+v*ocLP7OzTtHNu*TgT-9SsVc zG(-J@p`2MR=4E(XGuCp|I-@_(G~d~nmHJ%-UcDdE6_iK)@A#XR>mU8+7*-h(@;al%XpNl<&8f;UaAgNiv@$XP`WI0TI zKH2iQ9aeUl{KO+PO?hX3Xd&Lg-|hM{zk18Hr3utjgvV;KI=qp@6e`?wD}Zxf{6TH4 zGkXTokD`#IA}hEEh2{P=iOu?Sp(i>46lJtDCSU`X@@~xY@9d4mYavN9-YUQK zL3J=-&V;Y$HUA7n|2;GR=efiDrRI#+x5_jk9MF^k?kW`lbww)c4E0$7ESP_-O#@{y zlDbMrXHIG8UPB~1*VpD^gPh)O5@?fCE6@xAUdtEld=e0!aht(Ti#g%03|WVVdA~8;|hYBC=}qaQ0#7&k&A9Jl`58&z-J+VT_C~zhcfx>KDW05wKO%C_UMe zixJQp-lxf-=Ndi9lV$p$6dn^B&JLCUe^fD2nMz{pAdRRk)xKoBu0iMqAPTCZ%V&^~ zDm2w(?yvs^-9ra9!YdrG=&_{mz8&V!p#AU>0P#NXdIL1kqcyvX z$6r5@Uo(^4K2g;Hfc5}{uXH(|R*L7;Y$=x;S!3E5CuVv@kS}`e*O077??3F9nvC?Jd!zUFJ!$^<+E6mf03xEhTxV8QV0`w9eL$ihbMx8(WefrHRvOM$LR|_|Mx@NDOYUZT1J-S z+TYlr(#_4!jeOvt0rOV-V4Wt5R>-1J25`%(K!f> zR%rZpDCf1(@_d0>OhjeU!7$gNsOVO`Fw3*~`Y@whbf}hHvQj`JY6D^XZdW~AXH#*4 z<7&0;9t`rWQ1plW?reDOU(|I|DQ=S}=BUlmD-#l^%?W(<7w-B@W0H$PI<3!*)13mN&|)Dc~a8+^Zi zj%%mPx00=eKLZQQ;kDN1!$h?1<%_id1`RtMIVzucv^3dRLN4_bYj7zbA^AYmb8LN@ z`5NvRXGB*!oP+NNd^v%Eak-+;m~r;^NVtYMAR=o39?rL> zi6W(C zzY9d#mhqcikp6EUH^r>;0NUib)QQS5wuIgMP~_Tj1T=wGI^kmbtteYWq`hom^2v{tTM=iGf^$tOZxEf%>aO zgXqE}>B0$NOBs6EXxgh-y&ynZSg?ml#Kj?6d8lPW15VkZdfI#bDO*{wV}#*~9vn+i z&43Uz`i!ax3iZzvWfzdF-HWqXSIdh}{6UMfMXiQ}8&pVdCY)|nd=CkhCbL6gp92+I zf6l(<-d@GHqi-O4}RmX^*~=CO%C zW7k!}Z!q=cYdPV#WkuItr+TZoKXQBFK$y14u;pS5lE^M|7a zte8&&%54noC>Xbw_`FbT*pr!OD=xzS2%)Ho0O;sN9}glsgFwApYdj*(D}{4$24LQh zh=l;j?inQ6{@9Gjgl5DxG+-eBDw(<{s1VMA-KR7oZo!5*H$w)EH0No~3D2qc3 ztOcM~=P}!r1QWI=1)aFELh^SizNvq8;u00W9tK_Dt4+o}e&W6}iW54VQWHOKd)Xf?ceo#$fX723`J1aOsx)FCuEO``6;mc{qM zU63NN?+an}dcd^|pbs~h^b~c%A$ z`5Ar}LAe%>d(pDJl5FO0Fq{dSdF9(+C6GpEu+EBb%oI%C3?+~wW4UBN!g^f9D|-A5HN%a7UJYQ7GU&IgsYE#5 z;qqM~1tb-zIkxojx8(DBr!ns(#!kZe$FKP!*XxVG8T`K8;!kyemgLkTvWA?4(jb4* zITKKqovMDZ?tB;(LD$*OyXb57@FzN$r?Hrfh^FR&w?Y*|)TOq^+VRzNgUMc;D~k6} z{yrZ>`2bmIjh&v_NV4i?S5ETHamGKNY$nJ&Vgzt6wNFFih-sJODzKYt_jB-2j(4Y* z$9cqqgiD80NU+uNGejeCZbBdXX$Z{un13x07e%sJXNRJui%4LsT`3f*xH@LISo5r* zTk2*#EXNiQZ0BhS7CTxmm&QVe^Ip`h@RN?vm_7caxWlCdR#4n*>~YA7)c6NpxrXd# zRktlJSaNobl&?)<{zZPZ^GZSQp#K|Fpe&n-q7h95G^|`J~E^NJTp=R%72*#dQR0VYLghb$5b=M^Y7EGo2KpCRybI>le3{O!|kU-R&#YyED( zU~$uH{rMumc~`(xvQF~=qFVjq8p#(hmrJ-Nv~nMCl-kkdJIhTb8olP3kDv?|_~_II zsmqoN+KqJ1XR40Jx3fm2oy8)E8zxP1r0SlQW;9iEA9t-qo%``>UA-vck#DQcj=f3V z?-9u{M{Wgv5fy%U3sb-|PG>vptdNEqF3*X4=fuH@OH8Z) zEADliDV98C+A#48RWu*gRH?LV=5sQTn35VKzBJ?>5hrI&zt?iE+~2VE8Gsz>35y^< zxmoOX?PJC%OPF4AsJBq$`5x_@PaWFpgpYWgvZpIDst%RlUuE9bVUNGMDAhTs2dEHz z@c8|{v}X?}?YaXXU5o9wV1S8p=S+ZS`2RhR!U<*jDqCVCbvMMXu@fMS2|PoW(rzdu zX#$YU+d!$^-RW_Yj|q3H28MqR1ut7T+SN!P{zr)~As&mH6Nk5;U#{5KYbCBG3h_a+OaP{r6!bWGcrxc(8bp8 zPzxluP&##=MHJkqpF z8!L_MzFiVu?oKfT8ecF?j^}P(>T8d!Ml}<#xLyp(sDKeJ4u`ex)$sU`+B_SVE?a(v z2+b2;WwAid!b{9DWn$4drp`)j&)4@r`R9$_2gGX-S$v1Y>h+KdE;TxDAmW}SwU~2L9 z{>3-w?)WF);JDU{{vleY^fEtv=*vf+-S4BjP%3;`?0E?Es!~Laz0s|sF}5J(3SjB| z%`_-in5|F0Gj6|i4eJk8JC@sg)R!O`=jSc>PgsA)0Mpv-5zKV}e|vFhX+J!sc~;J9 zoo&wvkuaake6{gGtk*?FWvlw(-2K{z6&(iZww9ja%E}DO4DIO1Zi%DTl~~)Vl9zVa z>CwX5@h^+QV&{$kYJz8+^M|o|fSTa+UKt}%zLR@~bD0~EXE>5R)YbJy!GqRx{RgfS zw~!EH?7+j}h>4;>TahZNCI0VXM$7K{836uoox})^rr2~#Ghb;;BAxY=*TDN8QoCpL zrny!W&SS7C&JOf%-MvaHvG&fRYxJM}+^`?1Ix6-ly0+I_9w^?gvjH5EE~j9?GD$}9 zCGhm(*CO_%^mMdxF9`6uylT}jDxn~qPxfc4HbYKU@3q-!$Y=%BCf;C@QcM&gSC%yC*Ac# z!bxSx*iM#y0HXGmmk_6>WaZYKnrG~Gw<{<;lIbs%NR2Kxb`ecva2{O|R9-tkMpX2AsU3bApclmVBy!R$Z)hU022K4P$?!LWYJ_8m+Bd<<86VoA^RXxb4x@oz_KYL5;T$v0e2U43sxeluh{~9;Ui=J-?;*t zrr;2>y%lC=>PB6a1AKus!PSo@oc~DA>Bq0fUcyUMogu`^a&GaL#^HfhyRn(UFhD-d zxn?PrrB+#U9XQAtnMG2$F8$%79r=bmZu=zv9E&ApN|0RKB|rZaSkkv792~k^x1C@Q z@462mkdDr-?`6J0h1r@ey6Cs28j2k!n1@(h1copERYBF zy?vqr#Ayxub;!L*_K{Uf%atHHc=|$R%y{#X6!a;ywg-`!dhx|=i#RH3n*QV<$)d;3 zjmBASDx(cgOl{EO8M)vFkcGAgM(sNx!QylqpLN9|Xpd_Iim$WgYlgsu+aHF2#_6u$ zbty*h9==C89D$rqtK0ruvDzdR`*??W#Fn{Uya3xepG(?!|6YjstPSX-oYox zkL5B1=;&l3ktF*0mBv%Xc$QJFt&F22#nYx~c*X$t9oPlX-yF^rIU%)sl5{cE@#V95 zACuX7a%dlk2P`8Z!sp_Aq+uvy8lq^kJb>4pn<;e?_LM>lH5mXcOgbAtdtn2J#O9;# z30y<{kitLXL(N!yZ^MDMjrA6Yz=-<@^$@ZjRgi-C4OJH0593@>QJ5R_KIQHdv)kiR ziy6!dE^4_r3IZtEA=%7rV*{ZFJVqR|uRgXIBWzeOJ%AH#9ZO1*+2uLnDs|8`+E&j| za=RR1F!#rfn5?&Bq^}cU>bYrqV3mpMUQUBQCGoO=_%LYQDJ+-MF^l`nP4|MYwWI@i zVz7RsbM+C(RrfFF1U`st=pxECs3kHQww2x^CkV9j`3!?;&syuRrb#AO*>)P{C%11q z+RMGaX6F1DHS;hzuJxxCAgVaHtRlZ2`ng1XGGvLDsww?n)J%a`-h2IC7YNS6)-`%VQ86G(e2htz0D;=9K0t(6 zVVy%1A|GD1NB$@beM$Mn6|CVyN+*O1n$`GfFr=c6WF?V zI=&SKQ*TjHzD4;}{Z_O;fGQWx-JWpxw7W1KbX}RH47ixRN5S`!QpB#@9G%Xn-xgv! z!?AKK$b@#m7S-fM=ekvd5s%a4es=vaixYaySy+FWm^Ax+o@3M7)$9f^)4coUOT^hj zNQES+>R~&1X>I1ac2wt?!cOf2G1+&FmSQeN+Nu)Ltp*49I;-r~>@{Z%{e0l9{HJa! z&nNVeKihXn1fPt85}TBCTugr2Kj3Jw?bIvbuzG&2Nl~weHnloVGAl(eEG-2&S_ka& z0j^O6zP_V?KhK#RU^F)WI}-dC$G^aQ+4gvR5AIf_Sx@aa*eUrPP%>liT!W$Ct?i1M zc70cmh%Z9fclI7BNkroV@AR~m1IE;jhsiot{sjV|c{&>V!p66r6pyb0@VNIKU;+C? z)7v94e~jR4^)t{g$v+wfMf(Cxka2=Q z)h$ZMXh0TVPc_*yv;!|&wcr1P=YXfn_NHd^bL$QOIfUwYueWP+zuw)jZ~*p>-*kD9 zOVi``XK!}1xqWEPZr4p3<;9OW#GzQJ7l7Pnx&q#c~>qnfXh#~}4p<*g z@Ggfk0r#KYzc%>C45))py#H-)w!akx^Z**kG|Htixjy+bpfaV4fY^ZYUtRJKQv)Hx zp1}wNwEow>-T7pex%rv?+VZby@Nb5kG{QZV^*7_5&wg6gC7))i*~tAnzG{ns?M7@6Iq-&-Jq$Ty~)w zk30ZFO6+pJNF@L@#dnC%O8`$s1N(gHzlj3od5(@I8^i^DVgi1_z?AkOi7E@xYR(?F zh}(&cF%Ny|^+s-hz|(hV|7*B9{M~GiB*1oY{=3ir*5~izpmI%?!=;~(R=FvVm|;p7 zkDcdj4kqw3tQt;i>_QVo-~>XRY+7DYp;U~!4GEDJ8Q*zkFV-K@BTGCzx+abdtt|0@ z-)^v;I`c6Sai}+LQ3GBY^QwOKdp5#fLTAF9fZFhkm~i&FhUrfj_3W>oYj-T9<@;vx zgN}DsSU{k99jVpCmQH;X$#j}==yFTO7HWMEIHM8?-t`|kK8#A7dF8n6rQ!Bkc$Rti%+qTMGYjGLH@F$EM9qM=;_A;=W z8GHK32i^&k=Hs4u*K>piBarb&Ym;Oqpdxcwyw;Md@9l0M@<{W3o$P{|Vq0-Ib>ZnP zogXXC3fxZGFScu!r_uOU4-9Z@Y}8EK>=*NJAGfsaCC*8%&(V!8*x z8VHS#*NrS?$v}7&)LRNn-p<4uiT!Bna)>sENu}KMo4jx9?$9T%&0@P2d=oT(EVzV8 z9KabI>?hZvzn0X$^Vf0YRAWSU0DC!#{)>L5j*Hctyl*fU)q?=?@j@YL3a-oMx#ggQ zoAgt9kPW{Q*is`W#;DM>p&zV)?*G-GamV+zjGX(!-l((O9VLy<){m8M$wo~`Zh)G; z3cf&pWtkB6$Qm>pN|S<|=cKZJgr!rAR9Dw%WS*=~rnO%r>@zWhOfus~K zUq4G)bExTYsbw3}T=vg9d#!VTrJx6(VeGl}^siLV8?Yf^?U-YqNV7A(qZ5D{mW;qX z0v0~mUw|`)+`e8r|6W1=cOCz(>Z{~cPW{(4+g1{2;?+V|3`tm;jUIPBY literal 0 HcmV?d00001 From ff1c1c831764450b2f6cb268b43c9d23a8d3bde9 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 20 Jan 2015 15:41:49 +0800 Subject: [PATCH 07/25] add strategy pattern --- BehavioralPatterns/Strategy/README.md | 88 +++++++++++++++++++ BehavioralPatterns/Strategy/res/Strategy.png | Bin 0 -> 9903 bytes BehavioralPatterns/Strategy/strategy.py | 49 +++++++++++ 3 files changed, 137 insertions(+) create mode 100644 BehavioralPatterns/Strategy/README.md create mode 100644 BehavioralPatterns/Strategy/res/Strategy.png create mode 100644 BehavioralPatterns/Strategy/strategy.py diff --git a/BehavioralPatterns/Strategy/README.md b/BehavioralPatterns/Strategy/README.md new file mode 100644 index 000000000..47989b872 --- /dev/null +++ b/BehavioralPatterns/Strategy/README.md @@ -0,0 +1,88 @@ +# 策略模式 Strategy + +## 意图 +定义了一系列的算法,对其进行封装,使他们互为可交换。策略模式使得各算法在使用时能够切换。 + +为了解决某个问题、实现某个功能,存在多种方法(或算法),将这些方法全部在调用对象中实现显然不合理。将这些方法抽离出来单独实现,称为“策略”,使用时根据需要选择合适的策略装载,大概就是策略模式的含义。 + +## 适用性 +* 策略模式提供了将一个类与多种相似相关行为之一关联的方法; +* 你需要同一算法的不同变种; +* 算法数据中包含了用户不必知道的细节,使用策略模式以免暴露复杂的、算法相关的数据结构; +* 一个类定义了许多行为,会在一个多条件判断中选择执行哪种行为。使用策略模式替代这种条件判断; + +## 结构 + +![structure](./res/Strategy.png) + +* ContextInterface调用Algorithm的时候,需要将所有的必要参数传入,或者将自身引用传入; +* 由用户选择具体策略,传递给Context,再调用ContextInterface执行策略; + +## 模式效果 + +1. 相关算法家族 + + 通过这样的抽象架构能够提取出算法的公有功能。 + +2. 继承之外的另一种选择 + + 策略模式符合“使用组合,而不是继承”的原则,更为灵活。 + +3. 通过使用策略模式,去除了大量条件分支语句 +4. 具体实现的选择 + + 为相似的行为提供了不同的实现,由用户根据时间、空间的取舍决定具体的实现。 + +5. 用户必须理解不同的策略 + + 用户必须了解自己的选择的后果,了解所有备选算法的实际功效。 + +6. Strategy和Context之间的通信 + + 由于所有的策略都有相同的接口、相同的参数,就存在复杂算法需要更多参数,而简单算法可能完全不需要参数。为了复杂算法准备的参数,在选用简单算法时就显得累赘且浪费时间。 + + 如果想要解决这一问题,就要求Context理解Strategy接口的参数含义,而这又造成两者不再是松耦合状态。 + +7. 对象数量的增加 + + 策略模式增加了应用中对象的数量。一个解决办法是将策略设计为无状态对象(没有类成员变量,只有成员方法),然后让Context共享这些策略。 + + 蝇量方法对于这类实现更有心得,会在相关章节中详述。 + +## 实现 + +1. 定义Strategy和Context接口 + + Strategy和Context的接口必须提供ConcreteStrategy必要的参数,有两种方式: + + * 将参数以参数列表方式写在接口中,做到了Strategy和Context的解耦,但可能会给Strategy传递不必要的参数; + * 将Context本身的引用传递给Strategy,Strategy记录该引用,需要什么参数就获取什么参数,这样两者的耦合程度就更高。 + + 根据实际需要决定使用哪种方法。 + +2. 将Strategy作为模板成员变量 + + C++ 模板允许将Strategy作为模板变量使用: + + // Context + template + class Context { + public: + void Operation() { theStrategy.DoAlgorithm; } + + private: + AStrategy theStrategy; + } + + // Strategy + class MyStrategy { + public: + void DoAlgorithm(); + } + + // sample + Context aContext; + +3. 将策略设为可选 + + 在使用前先判断策略是否有效,如果无效则使用Context的默认方法,如果有效,则调用策略方法。 \ No newline at end of file diff --git a/BehavioralPatterns/Strategy/res/Strategy.png b/BehavioralPatterns/Strategy/res/Strategy.png new file mode 100644 index 0000000000000000000000000000000000000000..b3c0386ce4cebabae01b63d135fb3c65c11fdc3e GIT binary patch literal 9903 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 literal 0 HcmV?d00001 diff --git a/BehavioralPatterns/Strategy/strategy.py b/BehavioralPatterns/Strategy/strategy.py new file mode 100644 index 000000000..8c7a9b5a4 --- /dev/null +++ b/BehavioralPatterns/Strategy/strategy.py @@ -0,0 +1,49 @@ +# http://stackoverflow.com/questions/963965/how-is-this-strategy-pattern +# -written-in-python-the-sample-in-wikipedia +""" +In most of other languages Strategy pattern is implemented via creating some +base strategy interface/abstract class and subclassing it with a number of +concrete strategies (as we can see at +http://en.wikipedia.org/wiki/Strategy_pattern), however Python supports +higher-order functions and allows us to have only one class and inject +functions into it's instances, as shown in this example. +""" +import types + + +class StrategyExample: + + def __init__(self, func=None): + self.name = 'Strategy Example 0' + if func is not None: + self.execute = types.MethodType(func, self) + + def execute(self): + print(self.name) + + +def execute_replacement1(self): + print(self.name + ' from execute 1') + + +def execute_replacement2(self): + print(self.name + ' from execute 2') + + +if __name__ == '__main__': + strat0 = StrategyExample() + + strat1 = StrategyExample(execute_replacement1) + strat1.name = 'Strategy Example 1' + + strat2 = StrategyExample(execute_replacement2) + strat2.name = 'Strategy Example 2' + + strat0.execute() + strat1.execute() + strat2.execute() + +### OUTPUT ### +# Strategy Example 0 +# Strategy Example 1 from execute 1 +# Strategy Example 2 from execute 2 From 55885280b49eb50736387504a1545dff1eda581e Mon Sep 17 00:00:00 2001 From: luchengchao Date: Wed, 28 Jan 2015 15:40:28 +0800 Subject: [PATCH 08/25] add template pattern and singleton pattern --- BehavioralPatterns/TemplateMethod/README.md | 41 +++++++ .../TemplateMethod/res/TemplateMethod.png | Bin 0 -> 11768 bytes BehavioralPatterns/TemplateMethod/template.py | 107 ++++++++++++++++++ CreationalPatterns/Singleton/README.md | 92 +++++++++++++++ .../Singleton/res/Singleton.png | Bin 0 -> 7867 bytes 5 files changed, 240 insertions(+) create mode 100644 BehavioralPatterns/TemplateMethod/README.md create mode 100644 BehavioralPatterns/TemplateMethod/res/TemplateMethod.png create mode 100644 BehavioralPatterns/TemplateMethod/template.py create mode 100644 CreationalPatterns/Singleton/README.md create mode 100644 CreationalPatterns/Singleton/res/Singleton.png diff --git a/BehavioralPatterns/TemplateMethod/README.md b/BehavioralPatterns/TemplateMethod/README.md new file mode 100644 index 000000000..c0ec409c9 --- /dev/null +++ b/BehavioralPatterns/TemplateMethod/README.md @@ -0,0 +1,41 @@ +# 模板方法模式 Template Method + +## 意图 +定义算法的主体框架,而将其中的某些步骤移交给子类决定。模板方法在不改变算法框架的前提下让子类能够重新定义部分步骤。 + +模板方法针对的是一个具体的方法,将其步骤模板化,而实现的过程交给了子类。 + +## 案例 +以项目开发的一般周期来说,不同项目实施方案肯定不同,但都可以归纳到同一个模板:需求收集、立项、设计、开发、调试、发布。这样一个开发的流程就是一个模板方法。 + +## 适用性 + +1. 将算法中不变的部分一并实现,将可变部分留给子类实现; +2. 各个子类中有相同的行为或代码,将这些整合在模板方法中; +3. 限制子类的扩展。符合“开放封闭原则”,开放的是部分步骤,封闭的是整体框架,每个开放的部分对于子类就是一个“钩子”,子类只能在这些部分进行扩展; + +## 结构 + +![structure](./res/TemplateMethod.png) + +## 模式效果 + +模板模式引出了一种控制结构,一般称为“**好莱坞原则**”——“不要来找我们,我们会找你”。这里AbstractClass就是好莱坞大导演,而ConcreteClass就是试镜的小演员,ConcreteClass只负责自己有限的职责——实现Operation1和Operation2,调用工作有AbstractClass负责。 + +AbstractClass必须明确哪些方法是可以被重写,哪些是必须被重写,而哪些又是不能被重写。 + +## 实现 + +1. 合理使用C++的访问控制 + + * primitive方法是必须被重写的,必须为纯虚函数,确保子类会重写; + * 为了确保primitive方法不被外部访问,可以设置为protected权限; + * 模板方法是不希望子类重写的,不能设为虚函数; + +2. 尽可能减少Primitive方法的数量 + + 能够简化子类的实现。 + +3. 命名规则 + + 通过使用命名规则来提示子类的继承实现。 \ No newline at end of file diff --git a/BehavioralPatterns/TemplateMethod/res/TemplateMethod.png b/BehavioralPatterns/TemplateMethod/res/TemplateMethod.png new file mode 100644 index 0000000000000000000000000000000000000000..9577edd4021879e78e511f066bb907dea7c5d496 GIT binary patch literal 11768 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 literal 0 HcmV?d00001 diff --git a/BehavioralPatterns/TemplateMethod/template.py b/BehavioralPatterns/TemplateMethod/template.py new file mode 100644 index 000000000..42e7377ee --- /dev/null +++ b/BehavioralPatterns/TemplateMethod/template.py @@ -0,0 +1,107 @@ +"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ + +An example of the Template pattern in Python""" + +ingredients = "spam eggs apple" +line = '-' * 10 + + +# Skeletons +def iter_elements(getter, action): + """Template skeleton that iterates items""" + for element in getter(): + action(element) + print(line) + + +def rev_elements(getter, action): + """Template skeleton that iterates items in reverse order""" + for element in getter()[::-1]: + action(element) + print(line) + + +# Getters +def get_list(): + return ingredients.split() + + +def get_lists(): + return [list(x) for x in ingredients.split()] + + +# Actions +def print_item(item): + print(item) + + +def reverse_item(item): + print(item[::-1]) + + +# Makes templates +def make_template(skeleton, getter, action): + """Instantiate a template method with getter and action""" + def template(): + skeleton(getter, action) + return template + +# Create our template functions +templates = [make_template(s, g, a) + for g in (get_list, get_lists) + for a in (print_item, reverse_item) + for s in (iter_elements, rev_elements)] + +# Execute them +for template in templates: + template() + +### OUTPUT ### +# spam +# ---------- +# eggs +# ---------- +# apple +# ---------- +# apple +# ---------- +# eggs +# ---------- +# spam +# ---------- +# maps +# ---------- +# sgge +# ---------- +# elppa +# ---------- +# elppa +# ---------- +# sgge +# ---------- +# maps +# ---------- +# ['s', 'p', 'a', 'm'] +# ---------- +# ['e', 'g', 'g', 's'] +# ---------- +# ['a', 'p', 'p', 'l', 'e'] +# ---------- +# ['a', 'p', 'p', 'l', 'e'] +# ---------- +# ['e', 'g', 'g', 's'] +# ---------- +# ['s', 'p', 'a', 'm'] +# ---------- +# ['m', 'a', 'p', 's'] +# ---------- +# ['s', 'g', 'g', 'e'] +# ---------- +# ['e', 'l', 'p', 'p', 'a'] +# ---------- +# ['e', 'l', 'p', 'p', 'a'] +# ---------- +# ['s', 'g', 'g', 'e'] +# ---------- +# ['m', 'a', 'p', 's'] +# ---------- diff --git a/CreationalPatterns/Singleton/README.md b/CreationalPatterns/Singleton/README.md new file mode 100644 index 000000000..4b241e723 --- /dev/null +++ b/CreationalPatterns/Singleton/README.md @@ -0,0 +1,92 @@ +# 单例模式 Singleton + +## 意图 +确保类只有唯一的实例,并提供访问该实例全局入口点。 + +## 案例 +单例模式太常见了,以至于想不到什么特别的经典案例。 + +开发中非常常用这一模式,比如配置管理(全局只有一份配置,各处有访问的需要) + +单例模式提供全局唯一的入口点,除此之外无法创建对象。 + +## 适用性 + +* 对象必须有且只有一个实例,且有一个能够访问该对象的入口点; +* 当子类需要扩展这一单例,用户能够使用这一扩展的单例而无需修改他们的代码; + +## 结构 + +![structure](./res/Singleton.png) + +`Instance()`方法是外部访问Singleton实例的唯一入口点。 + +## 模式效果 + +1. 管控对单个实例的访问。 +2. 简化的命名空间 + + 使用单例模式是对使用全局变量的一种改进,能够使得命名空间保持整洁清晰。 + +3. 允许精炼操作和表现 + + 单例也是可以被继承的,能够使用某个单例来配置应用。这样你就可以在运行时选择单例完成应用的配置工作。 + +4. 控制实例的数量 + + 单例模式同样允许让Singleton类有多个实例对象,只需要修改那唯一的入口点即可。 + +5. 相比与类方法更为灵活 + + 相比于使用类方法,使用单例访问成员方法更为灵活。 + + 另外,C++中静态方法(static)永远不能是虚函数,子类也就不能多态复用。 + +## 实现 +1. **确保**只有唯一的对象 + + 代码实现中往往只提供唯一访问对象的入口,而将对象创建方法隐藏。该入口确保返回的唯一的对象在返回之前完成初始化。 + + 以下是C++中的最基本的实现方式: + + // Singleton.h + class Singleton { + public: + static Singleton* Instance(); + protected: + Singleton(); + private: + static Singleton* _instance; + }; + + // Singleton.cpp + Singleton* Singleton::_instance = 0; + + Singleton* Singleton::Instance () { + if (_instance == 0) { + _instance = new Singleton; + } + return _instance; + } + + 对于C++,不将_instance定义为全局或静态对象,主要出于以下几个理由: + + * 无法确保只有一个静态对象被声明;这是一个责任的问题,本类型的单例,就该由本类型确保其唯一性,而不是将其托付给其他角色; + * 单例对象的创建可能需要一些值,这些值必须是程序运行过程中才能取得的; + * C++没有对全局对象的创建顺序有明确定义,这使得使用全局对象作为单例实体,就不允许对其他对象存在依赖,没有必要添加这一限制; +2. 单例类的继承 + + * 通过唯一入口实例化时指定具体的子类类型。**C++中static方法是不能为虚的**,如果存在多个子类需要有某个特定的Tag方能实例化; + * 将实例化方法从基类转移到子类中; + * 使用**单例注册表(registry of singleton)**。提供注册和查找的静态方法,子类负责向基类注册单例,使用时在注册表中查找已注册的单例进行使用 + + class Singleton { + public: + static void Register(const char* name, Singleton*); + static Singleton* Instance(); + protected: + static Singleton* Lookup(const char* name); + private: + static Singleton* _instance; + static List* _registry; + }; \ No newline at end of file diff --git a/CreationalPatterns/Singleton/res/Singleton.png b/CreationalPatterns/Singleton/res/Singleton.png new file mode 100644 index 0000000000000000000000000000000000000000..e1e0592eeb2ca4e568fa74b7b151a8ead546c172 GIT binary patch literal 7867 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 Date: Tue, 3 Feb 2015 16:46:59 +0800 Subject: [PATCH 09/25] add flyweight pattern --- StructuralPatterns/Flyweight/README.md | 67 ++++++++++++++++++ StructuralPatterns/Flyweight/flyweight.py | 42 +++++++++++ .../Flyweight/res/FlyweightObj.png | Bin 0 -> 6817 bytes .../Flyweight/res/FlyweightStructure.png | Bin 0 -> 17418 bytes 4 files changed, 109 insertions(+) create mode 100644 StructuralPatterns/Flyweight/README.md create mode 100644 StructuralPatterns/Flyweight/flyweight.py create mode 100644 StructuralPatterns/Flyweight/res/FlyweightObj.png create mode 100644 StructuralPatterns/Flyweight/res/FlyweightStructure.png diff --git a/StructuralPatterns/Flyweight/README.md b/StructuralPatterns/Flyweight/README.md new file mode 100644 index 000000000..f171088cc --- /dev/null +++ b/StructuralPatterns/Flyweight/README.md @@ -0,0 +1,67 @@ +# 蝇量模式 Flyweight + +## 意图 +使用共享方式高效地支持大量的粒度细的对象。 + +又称为享元模式。 + +## 进一步说明 +蝇量模式的核心可以认为就是存在一个蝇量对象池,对象池中的对象记下对象的内在属性,当需要获取对象时首先尝试从池中取出对象,取不到时才考虑创建。 + +例如,内存池。 + +## 适用性 +蝇量模式的效果非常依赖于使用场景,确保只有在以下条件**都满足**时,使用蝇量模式: + +* 应用中会有大量的对象; +* 存储这些大量的对象会非常耗费资源; +* 对象的大部分状态是外在的; +* 一旦将这些外在状态移除,许多对象能够用相对较少的共享对象替代; +* 应用不依赖于对象标识。因为蝇量对象是共享的,只要逻辑上不同的对象,即使共享了同一个对象,也能被认为带有不同标识。 + +## 结构 + +![structure](./res/FlyweightStructure.png) + +下图展示了通常蝇量模式是如何使用的 + +![structure](./res/FlyweightObj.png) + +### 核心角色责任 +* Flyweight + * 申明一个接口,接收外部状态并执行相应操作 +* ConcreteFlyweight + * 存储内部状态,实现接口; + * 必须是可共享的,只能有内部状态,必须是上下文无关的; +* UnsharedConcreteFlyweight + * 并非所有的Flyweight都要是可共享的; + * 通常UnsharedConcreteFlyweight包含ConcreteFlyweight +* FlyweightFactory + * 创建、管理flyweight对象 + * 如果flyweight已存在,返回共享对象;否则,创建flyweight对象并返回 +* Client + * 持有flyweight的引用 + * 计算或存储flyweight对象的外部状态 + +## 模式效果 +蝇量模式可能会增加运行时处理外部状态的资源消耗,但是能够通过对象共享节省存储。存储容量与以下几个因素有关: + +* 通过贡献减少的对象数量; +* 每个对象的内部状态的数量; + * 空间和时间的取舍 +* 外部状态是否需要计算或存储; + * 通过计算而不是存储得到外部状态更能节省空间 + +蝇量模式经常和组合模式共同使用。 + +## 实现 +1. 删除外部状态 + * 模式是否适用很大程度上由能否很方便地识别出外部状态、并将其从对象中删除有关; + * 理想状态是外部状态能够非常容易地计算得到; +2. 管理共享对象 + * client不允许直接实例化共享对象,而应委托给FlyweightFactory; + * FlyweightFactory返回共享对象,或实例化对象; + * 可以使用引用计数维护共享对象,但在flyweight数量固定会较少时,没有这么做的必要 + + + diff --git a/StructuralPatterns/Flyweight/flyweight.py b/StructuralPatterns/Flyweight/flyweight.py new file mode 100644 index 000000000..efa489816 --- /dev/null +++ b/StructuralPatterns/Flyweight/flyweight.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://codesnipers.com/?q=python-flyweights""" + +import weakref + + +class Card(object): + + """The object pool. Has builtin reference counting""" + _CardPool = weakref.WeakValueDictionary() + + """Flyweight implementation. If the object exists in the + pool just return it (instead of creating a new one)""" + def __new__(cls, value, suit): + obj = Card._CardPool.get(value + suit, None) + if not obj: + obj = object.__new__(cls) + Card._CardPool[value + suit] = obj + obj.value, obj.suit = value, suit + return obj + + # def __init__(self, value, suit): + # self.value, self.suit = value, suit + + def __repr__(self): + return "" % (self.value, self.suit) + + +if __name__ == '__main__': + # comment __new__ and uncomment __init__ to see the difference + c1 = Card('9', 'h') + c2 = Card('9', 'h') + print(c1, c2) + print(c1 == c2) + print(id(c1), id(c2)) + +### OUTPUT ### +# +# True +# 140368617673296 140368617673296 diff --git a/StructuralPatterns/Flyweight/res/FlyweightObj.png b/StructuralPatterns/Flyweight/res/FlyweightObj.png new file mode 100644 index 0000000000000000000000000000000000000000..c8210bfaf6fd45dfe75340ce7c5d3e397957661f GIT binary patch literal 6817 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 UiKi;@>ItBv@KiqkvGJRK0%S2wjQ{`u literal 0 HcmV?d00001 diff --git a/StructuralPatterns/Flyweight/res/FlyweightStructure.png b/StructuralPatterns/Flyweight/res/FlyweightStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..d09d104d15bf5a3a7e7a3ad836b13dec0885356f GIT binary patch literal 17418 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 Q;{zo5UPi3=ou1GC0r;u!fB*mh literal 0 HcmV?d00001 From f339cec6b623d4564fceeb8ccb189167e26917f8 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 10 Feb 2015 16:55:06 +0800 Subject: [PATCH 10/25] add state pattern --- BehavioralPatterns/State/README.md | 61 +++++++++++++ .../State/res/StateStructure.png | Bin 0 -> 8489 bytes BehavioralPatterns/State/state.py | 80 ++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 BehavioralPatterns/State/README.md create mode 100644 BehavioralPatterns/State/res/StateStructure.png create mode 100644 BehavioralPatterns/State/state.py diff --git a/BehavioralPatterns/State/README.md b/BehavioralPatterns/State/README.md new file mode 100644 index 000000000..ad3795238 --- /dev/null +++ b/BehavioralPatterns/State/README.md @@ -0,0 +1,61 @@ +# 状态模式 State + +## 意图 +允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 + +一个对象的行为,会因为其所处的状态而发生变化,需要有大量的`if...else...`分支,此时就可以考虑使用状态模式。 + +## 适用性 +状态模式适合以下场景: + +* 对象的行为受其状态约束,在运行时依据状态会发生变化; +* 对象的行为有一大块依赖状态的条件分支语句。状态通常是一个常量枚举。状态模式将每个条件分支放在一个独立类中,使得处理每个分支转变为调用类方法。 + +## 结构 + +![structure](./res/StateStructure.png) + +* Context将请求委托给具体的State执行; +* Context可能会将自身作为参数传给State,使其能够访问Context内容; +* Client只和Context交互,能够通过接口设定State,并不直接访问State; +* Context或ConcreteState决定状态迁移的场景和方式; + +## 模式效果 +1. 将状态指向的行为本地化,并根据不同状态区分行为。将特定状态的相关行为放进了一个对象中;因为状态和行为绑定,方便添加新的状态; +2. 将状态迁移的过程隐藏; +3. 状态对象可共享; + * 状态对象没有实例变量,仅仅是根据类型进行编码,那就是可共享的状态对象; + * 天然的蝇量模式(没有内部状态,只有行为) + +## 实现 +1. 由谁定义状态迁移? + + 状态模式没有限定状态迁移的标准。如果这是固定的,则能够由代码的上下文决定状态迁移。更为灵活的方式是由子类决定迁移方式,这就需要一个额外的接口用于设定状态。 + + 不固定的方式对于添加新的状态更为灵活,但是使得子状态之间不再那么透明,每个子状态至少要知道一个其他子状态的,从而实现状态跃迁。 + +2. 一种基于表的(状态模式)替代方案 + + 创建一张表,将输入映射到状态迁移。对于每种状态,表将可能的输入映射到后续的状态。 + + 这一方案的主要优点是其规则性:能够通过变换数据,而非代码来实现规则的变化。 + + 然而,也有以下一些缺点: + + * 查表比(虚)函数调用更为低效; + * 将迁移逻辑归一化、表格化使其更加难以理解; + * 想要将额外的行为添加进状态迁移通常会比较困难; + + 表驱动的状态机和状态模式的差异总结:状态模式强调与状态绑定的行为,表驱动的状态机着眼于定义状态迁移。 + +3. 创建和删除状态对象 + + 一个实现时通常需要权衡的是状态对象的生命周期:是使用时创建,用完就删除,还是提前创建好,用完也不删呢? + + 前者通常在状态只有在运行时才能确定的场景下,而且环境较少变更状态,当状态中包含很多信息时,避免了创建这类状态的花费。 + + 后者对于状态迁移频繁的场景适应性更好,避免了频繁创建状态。但这种作法也有不方便之处,代码空间中需要维护针对所有状态的引用。 + +4. 使用动态继承 + + 部分语言支持。可将方法委托给不同类型的对象,实现某种程度的动态继承。 \ No newline at end of file diff --git a/BehavioralPatterns/State/res/StateStructure.png b/BehavioralPatterns/State/res/StateStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..65e673e6a962a230b898a0edb483d88babac1f87 GIT binary patch literal 8489 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 R6DWHD*_R67;unVg{|gJ6Z3X}U literal 0 HcmV?d00001 diff --git a/BehavioralPatterns/State/state.py b/BehavioralPatterns/State/state.py new file mode 100644 index 000000000..5f4ef41eb --- /dev/null +++ b/BehavioralPatterns/State/state.py @@ -0,0 +1,80 @@ +"""Implementation of the state pattern""" + +# http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ + + +class State(object): + + """Base state. This is to share functionality""" + + def scan(self): + """Scan the dial to the next station""" + self.pos += 1 + if self.pos == len(self.stations): + self.pos = 0 + print("Scanning... Station is", self.stations[self.pos], self.name) + + +class AmState(State): + + def __init__(self, radio): + self.radio = radio + self.stations = ["1250", "1380", "1510"] + self.pos = 0 + self.name = "AM" + + def toggle_amfm(self): + print("Switching to FM") + self.radio.state = self.radio.fmstate + + +class FmState(State): + + def __init__(self, radio): + self.radio = radio + self.stations = ["81.3", "89.1", "103.9"] + self.pos = 0 + self.name = "FM" + + def toggle_amfm(self): + print("Switching to AM") + self.radio.state = self.radio.amstate + + +class Radio(object): + + """A radio. It has a scan button, and an AM/FM toggle switch.""" + + def __init__(self): + """We have an AM state and an FM state""" + self.amstate = AmState(self) + self.fmstate = FmState(self) + self.state = self.amstate + + def toggle_amfm(self): + self.state.toggle_amfm() + + def scan(self): + self.state.scan() + + +# Test our radio out +if __name__ == '__main__': + radio = Radio() + actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 + actions *= 2 + + for action in actions: + action() + +### OUTPUT ### +# Scanning... Station is 1380 AM +# Scanning... Station is 1510 AM +# Switching to FM +# Scanning... Station is 89.1 FM +# Scanning... Station is 103.9 FM +# Scanning... Station is 81.3 FM +# Scanning... Station is 89.1 FM +# Switching to AM +# Scanning... Station is 1250 AM +# Scanning... Station is 1380 AM From c3b0b3fd5545b8f4bac64c0625383b5e6ccbfda4 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Sun, 15 Feb 2015 10:08:47 +0800 Subject: [PATCH 11/25] add builder pattern --- CreationalPatterns/Builder/README.md | 69 +++++++++++++++ CreationalPatterns/Builder/builder.py | 79 ++++++++++++++++++ CreationalPatterns/Builder/res/Builder.png | Bin 0 -> 10946 bytes .../Builder/res/BuilderSequence.png | Bin 0 -> 8535 bytes 4 files changed, 148 insertions(+) create mode 100644 CreationalPatterns/Builder/README.md create mode 100644 CreationalPatterns/Builder/builder.py create mode 100644 CreationalPatterns/Builder/res/Builder.png create mode 100644 CreationalPatterns/Builder/res/BuilderSequence.png diff --git a/CreationalPatterns/Builder/README.md b/CreationalPatterns/Builder/README.md new file mode 100644 index 000000000..a3dfb4b68 --- /dev/null +++ b/CreationalPatterns/Builder/README.md @@ -0,0 +1,69 @@ +# 生成器模式 Builder + +## 意图 +它可以将复杂对象的构造过程与其表现分离、抽象出来,使这个抽象过程可以构造出不同表现(属性)的对象。 + +## 模式比喻 +我要一座房子住,可是我不知道怎么盖(简单的砌墙,层次较低),也不知道怎么样设计(建几个房间,几个门好看,层次较高),于是我需要找一帮**民工,他们会砌墙**,还得找个**设计师,他知道怎么设计**,我还要**确保民工听设计师的领导**,而设计师本身也不干活,光是下命令,这里砌一堵墙,这里砌一扇门,这样民工开始建设,最后,我可以向民工要房子了。在这个过程中,**设计师是什么也没有,除了他在脑子里的设计和命令,所以要房子也是跟民工要** + +## 适用性 +在以下场合使用生成器模式: + +* 创建复杂对象的算法要与对象组织的部分分离; +* 对象的创建过程允许不同的表现方式 + +## 结构 + +![structure](./res/Builder.png) + +角色分析: + +* Builder + * 定义用于创建产品各部分的抽象接口 +* ConcreteBuilder + * 通过实现Builder的接口创建和组装产品的各部分 + * 定义和追踪其创建的表现 + * 提供取回完整产品的接口 +* Director + * 通过调用Builder接口创建对象 +* Product + * 代表了创建出的复杂对象。ConcreteBuilder构造了Product的内部表现,定义了其组装过程 + * 包含了组成Product的部件类,包括将这些部件组装成最终结果的接口 + +模式时序图: + +![structure](./res/BuilderSequence.png) + +## 模式效果 +1. 能够改变产品的内部表现。 + + Product通过抽象接口进行构建,通过定义一种新的Builder就能改变产品的内部表现。 + +2. 将产品的构造和表现分离 + + 生成器模式封装了复杂对象的构建和表现。客户不用知道定义产品内部结构的类。 + + ConcreteBuilder包含了所有的创建和组装某类产品的代码。这些代码只用写一次,不同的Director可以复用这些代码,来构造产品。 + +3. 对于构建过程提供了更好的控制 + + 与其他创建类型的模式不同,生成器模式在Director的控制下一步步构造产品,仅在产品完成后才从Builder中取回。 + +## 实现 +通常,Builder是个虚类,只负责定义接口,ConcreteBuilder实现这些接口创建产品。 + +以下是一些实现时需要考虑的问题: + +1. 组装和构建接口: + + Builder的抽象接口要能够支持所有的ConcreteBuilder的构建。 + +2. 为什么没有抽象的Product? + + ConcreteBuilder创建的Product可能千差万别,难以设定一个通用的抽象基类。 + + 通常用户给Director配置合适的ConcreteBuilder,所以用户能够知道具体的Builder子类正被使用,能够合适地处置产品。 + +3. Builder中接口默认为空 + + 在C++中,构建方法通常不能为虚函数,而是被定义为什么都不做的空函数,有用户来重写他们感兴趣的方法。 \ No newline at end of file diff --git a/CreationalPatterns/Builder/builder.py b/CreationalPatterns/Builder/builder.py new file mode 100644 index 000000000..3b04412d1 --- /dev/null +++ b/CreationalPatterns/Builder/builder.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding : utf-8 -*- + +""" +@author: Diogenes Augusto Fernandes Herminio +https://gist.github.com/420905#file_builder_python.py +""" + + +# Director +class Director(object): + + def __init__(self): + self.builder = None + + def construct_building(self): + self.builder.new_building() + self.builder.build_floor() + self.builder.build_size() + + def get_building(self): + return self.builder.building + + +# Abstract Builder +class Builder(object): + + def __init__(self): + self.building = None + + def new_building(self): + self.building = Building() + + +# Concrete Builder +class BuilderHouse(Builder): + + def build_floor(self): + self.building.floor = 'One' + + def build_size(self): + self.building.size = 'Big' + + +class BuilderFlat(Builder): + + def build_floor(self): + self.building.floor = 'More than One' + + def build_size(self): + self.building.size = 'Small' + + +# Product +class Building(object): + + def __init__(self): + self.floor = None + self.size = None + + def __repr__(self): + return 'Floor: {0.floor} | Size: {0.size}'.format(self) + + +# Client +if __name__ == "__main__": + director = Director() + director.builder = BuilderHouse() + director.construct_building() + building = director.get_building() + print(building) + director.builder = BuilderFlat() + director.construct_building() + building = director.get_building() + print(building) + +### OUTPUT ### +# Floor: One | Size: Big +# Floor: More than One | Size: Small diff --git a/CreationalPatterns/Builder/res/Builder.png b/CreationalPatterns/Builder/res/Builder.png new file mode 100644 index 0000000000000000000000000000000000000000..24071a66263cd8744a764cdaff1706843eab509d GIT binary patch literal 10946 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 D&0oRC literal 0 HcmV?d00001 From 0d1cf897f683e90410df5bc1221ab875ef975f2c Mon Sep 17 00:00:00 2001 From: luchengchao Date: Sun, 15 Feb 2015 14:37:39 +0800 Subject: [PATCH 12/25] add prototype pattern --- CreationalPatterns/Prototype/README.md | 72 ++++++++++++++++++ CreationalPatterns/Prototype/prototype.py | 50 ++++++++++++ .../Prototype/res/Prototype.png | Bin 0 -> 8945 bytes 3 files changed, 122 insertions(+) create mode 100644 CreationalPatterns/Prototype/README.md create mode 100644 CreationalPatterns/Prototype/prototype.py create mode 100644 CreationalPatterns/Prototype/res/Prototype.png diff --git a/CreationalPatterns/Prototype/README.md b/CreationalPatterns/Prototype/README.md new file mode 100644 index 000000000..ac598bad3 --- /dev/null +++ b/CreationalPatterns/Prototype/README.md @@ -0,0 +1,72 @@ +# 原型模式 Prototype +## 意图 +使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。 + +原型模式的核心在于原型提供的`clone`方法。 + +## 适用性 +当系统和产品的创建、组合、表现分离时,可以使用原型模式,另外: + +* 具体实例化哪个类是运行时才决定,或者 +* 避免构建与产品层级平行的工厂层级,或者 +* 类的实例只会有不同状态组合的其中之一。相比于每次实例化,从原型克隆(clone)会更加的方便。 + +## 结构 + +![structure](./res/Prototype.png) + +## 模式效果 + +原型模式有着抽象工厂模式和生成器模式相同的效果:向用户隐藏了具体的产品,减少用户需要了解的信息。另外,这些模式让用户只需要关心应用相关的内容,产品发生变化时无需做出改变。 + +原型模式特有的一些优势如下: + +1. 运行时添加和删除产品 + + 原型模式使你能通过注册原型实例,将一个新的具体产品合并到系统中,这比其他的创建型模式更为灵活。 +2. 通过改变值来指定新的对象 + + 高度动态的系统让你能够通过指定对象属性,定义新的行为,而非定义新的类。 + + 这一设计使得用户不用编码,就定义了新的“类”。事实上,原型克隆和类实例化很相似,原型模式能够大幅减少系统中所需的类的数量。 + +3. 通过改变结构来指定新的对象 + + 许多应用通过创建部件和子部件的方式创建对象,通过原型模式,我们可将各种部件作为原型,不同结构的部件作为不同的原型,简化对象的创建。 + +4. 减少子类 + + 工厂方法会创建与产品层级平级的工厂方法层级,而原型模式通过克隆创建对象实例,也就不存在创建方法层级。这一特性在C++这种不将类型作为一级成员(first-class objects)的语言中比较实用,在objective-c和python中效果不那么显著。 + +5. 配置应用动态加载类 + + 想要动态加载类,所依赖的构造方法就不能是静态的。通过原型注册和克隆方法,应用能够动态加载类。 + +所有原型的子类必须实现Clone方法,这对于已经存在的类是比较困难的(开发封闭原则,对类的扩展开放,修改封闭)。另外,对于不支持拷贝的对象Clone方法的实现也有难度。 + +## 实现 + +原型模式对于C++这样的静态语言很有帮助,这类语言中类型不是对象,运行时缺少类型信息。对于Smalltalk和Objective C这类语言的效果就不是那么明显。 + +实现原型模式时,需要考虑以下问题: + +1. 使用原型管理 + + 当原型种类不固定时,需要维护可用原型的注册表,用户可能不会关心这个注册表中的具体内容,但是他们会尝试存入和取出原型。 + + 原型管理负责根据给定的Key返回所需的原型,需要提供给用户的操作包括注册、注销、获取,有时还有浏览。 + +2. 实现克隆操作 + + 原型模式最困难的就是实现Clone方法,尤其是存在环形引用时。很多语言都支持拷贝操作,但该如何解决“浅拷贝还是深拷贝”的问题? + + 浅拷贝更加简单和高效,Smalltalk默认为前拷贝,C++的拷贝由成员类型决定,指针是共享一块内存的。而Clone方法大部分情况下需要深拷贝。实现时要根据具体的情况,决定哪些对象是可以共享,哪些是必须独立的。 + + 如果系统中的对象提供存储和加载操作,你能够使用Clone方法非常容易地实现:存储时就是Clone到内存,加载就是从内存中Clone得到对象。 + +3. 初始化克隆 + + 一些用户乐于直接调用Clone接口,而另一些希望能够向Clone提供一些状态或参数。向Clone操作中传递参数有碍Clone接口的一致性。 + + 如果原型类型提供了设置状态的方法,用户可以在Clone接口之后立刻调用,如果没有这样的方法,就需要引入初始化方法了。初始化方法传入参数,并设置Clone的内部状态。 + diff --git a/CreationalPatterns/Prototype/prototype.py b/CreationalPatterns/Prototype/prototype.py new file mode 100644 index 000000000..2f2a14a82 --- /dev/null +++ b/CreationalPatterns/Prototype/prototype.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import copy + + +class Prototype: + + def __init__(self): + self._objects = {} + + def register_object(self, name, obj): + """Register an object""" + self._objects[name] = obj + + def unregister_object(self, name): + """Unregister an object""" + del self._objects[name] + + def clone(self, name, **attr): + """Clone a registered object and update inner attributes dictionary""" + obj = copy.deepcopy(self._objects.get(name)) + obj.__dict__.update(attr) + return obj + + +class A: + def __init__(self): + self.x = 3 + self.y = 8 + self.z = 15 + self.garbage = [38, 11, 19] + + def __str__(self): + return '{} {} {} {}'.format(self.x, self.y, self.z, self.garbage) + + +def main(): + a = A() + prototype = Prototype() + prototype.register_object('objecta', a) + b = prototype.clone('objecta') + c = prototype.clone('objecta', x=1, y=2, garbage=[88, 1]) + print([str(i) for i in (a, b, c)]) + +if __name__ == '__main__': + main() + +### OUTPUT ### +# ['3 8 15 [38, 11, 19]', '3 8 15 [38, 11, 19]', '1 2 15 [88, 1]'] diff --git a/CreationalPatterns/Prototype/res/Prototype.png b/CreationalPatterns/Prototype/res/Prototype.png new file mode 100644 index 0000000000000000000000000000000000000000..b55e9a9949540fc59d0017a389b6bd4835e5e40c GIT binary patch literal 8945 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 Date: Sun, 15 Feb 2015 17:57:37 +0800 Subject: [PATCH 13/25] add bridge pattern --- StructuralPatterns/Bridge/README.md | 54 +++++++++++++++++ StructuralPatterns/Bridge/bridge.py | 55 ++++++++++++++++++ StructuralPatterns/Bridge/res/Bridge.png | Bin 0 -> 11367 bytes .../Bridge/res/Proliferation.png | Bin 0 -> 7342 bytes 4 files changed, 109 insertions(+) create mode 100644 StructuralPatterns/Bridge/README.md create mode 100644 StructuralPatterns/Bridge/bridge.py create mode 100644 StructuralPatterns/Bridge/res/Bridge.png create mode 100644 StructuralPatterns/Bridge/res/Proliferation.png diff --git a/StructuralPatterns/Bridge/README.md b/StructuralPatterns/Bridge/README.md new file mode 100644 index 000000000..343ec3f69 --- /dev/null +++ b/StructuralPatterns/Bridge/README.md @@ -0,0 +1,54 @@ +# 桥连模式 Bridge +解耦抽象和实现,使两者能够互不干扰地变化。 + +举例来说,画图,我可以画矩形,圆,三角形等等,在哪里画呢?我可以在pdf上画,也可以在doc上面画。画什么图和在哪里画都是可以独立变化的,此种情况就比较适合用桥模式。就是说设计中有超过一维的变化我们就可以用桥模式。如果只有一维在变化,那么我们用继承就可以圆满的解决问题。 + +## 适用性 +* 避免抽象与实现之间固定的绑定(例如子类实现接口方式),这样做能够实现动态切换实现。 +* 抽线和实现都会被继承。桥连模式使你能够组合不同的抽象和实现。 +* 抽象的实现的修改,不需要用户重新编译才能起作用。 +* C++中希望对客户完全隐藏抽象的实现,可以考虑使用桥连模式,因为在C++中类的表现在类接口中是可见的。 +* 系统中的类可能存在如下结构图所示的增殖情况,希望能摆脱这种糟糕的设计 + + ![structure](./res/Proliferation.png) + + >最顶层的抽象为Window,在不同的桌面平台有不同的子类XWindow和PMWindow。除了从平台角度划分,还可以从功能角度划分,存在基类IconWindow,而IconWindow也存在不同平台的实现XIconWindow和PMIconWindow。没种功能的Window都会存在多平台的实现,如果支持的平台增加了,没种功能Window也需要扩展对应实现。这就是所谓的类的增殖。 + +* 希望能在多个对象间共享实现,而且这个希望是能对客户隐藏的。 + +## 结构 + +![structure](./res/Bridge.png) + +## 模式效果 + +1. 解锁接口和实现 +2. 提高可扩展性 + + 能够对抽象层级和实现层级分别扩展,不变的部分能够正常运行。 +3. 向客户隐藏实现细节 + +## 实现 + +1. 唯一的实现 + + 有些场合只有一种实现,就没必要创建一个抽象的实现基类了。这是一种桥连模式的退化情况,但依然尤其价值。 + +2. 创建正确的实现对象 + + 如何决定该使用哪种实现? + + 如果抽象知道所有的具体实现类,就能在实例化时构造相应的实现。这所有的实现可以被存放在列表、或者映射中。 + + 另一种方式是初始化时选择一种默认的实现,然后根据具体使用变更实现。 + + 还有一种方案是将实现的选择委托给另一个对象,例如可以是一个抽象工厂,工厂负责返回对应的一整套实现,好处是抽象并不直接和任何实现类耦合。 + +3. 共享实现 +4. 使用多重继承 + + 部分语言支持多重继承(比如C++),一个子类能够public继承抽象,private继承具体实现,从而达成预期效果。 + + 但这一做法使得抽象和实现永久绑定,本质上已经不再是桥连模式了。 + + diff --git a/StructuralPatterns/Bridge/bridge.py b/StructuralPatterns/Bridge/bridge.py new file mode 100644 index 000000000..1c3c07472 --- /dev/null +++ b/StructuralPatterns/Bridge/bridge.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Bridge_Pattern#Python""" + + +# ConcreteImplementor 1/2 +class DrawingAPI1(object): + + def draw_circle(self, x, y, radius): + print('API1.circle at {}:{} radius {}'.format(x, y, radius)) + + +# ConcreteImplementor 2/2 +class DrawingAPI2(object): + + def draw_circle(self, x, y, radius): + print('API2.circle at {}:{} radius {}'.format(x, y, radius)) + + +# Refined Abstraction +class CircleShape(object): + + def __init__(self, x, y, radius, drawing_api): + self._x = x + self._y = y + self._radius = radius + self._drawing_api = drawing_api + + # low-level i.e. Implementation specific + def draw(self): + self._drawing_api.draw_circle(self._x, self._y, self._radius) + + # high-level i.e. Abstraction specific + def scale(self, pct): + self._radius *= pct + + +def main(): + shapes = ( + CircleShape(1, 2, 3, DrawingAPI1()), + CircleShape(5, 7, 11, DrawingAPI2()) + ) + + for shape in shapes: + shape.scale(2.5) + shape.draw() + + +if __name__ == '__main__': + main() + +### OUTPUT ### +# API1.circle at 1:2 radius 7.5 +# API2.circle at 5:7 radius 27.5 diff --git a/StructuralPatterns/Bridge/res/Bridge.png b/StructuralPatterns/Bridge/res/Bridge.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e4aec04faf726d6c26ea3f608354b5f4edc6f0 GIT binary patch literal 11367 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 Ak^lez literal 0 HcmV?d00001 From 3345e993e49e86c9e1c431ad5a2702a0547e2a55 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Wed, 20 May 2015 19:06:53 +0800 Subject: [PATCH 14/25] add chain of responsibility --- .../ChainOfReponsibility/README.md | 61 ++++++++++++++++ .../ChainOfReponsibility/chain.py | 66 ++++++++++++++++++ .../res/ChainOfResponsibilityObject.png | Bin 0 -> 4608 bytes .../res/ChainOfResponsibilityStructure.png | Bin 0 -> 7582 bytes 4 files changed, 127 insertions(+) create mode 100644 BehavioralPatterns/ChainOfReponsibility/README.md create mode 100644 BehavioralPatterns/ChainOfReponsibility/chain.py create mode 100644 BehavioralPatterns/ChainOfReponsibility/res/ChainOfResponsibilityObject.png create mode 100644 BehavioralPatterns/ChainOfReponsibility/res/ChainOfResponsibilityStructure.png diff --git a/BehavioralPatterns/ChainOfReponsibility/README.md b/BehavioralPatterns/ChainOfReponsibility/README.md new file mode 100644 index 000000000..10863d928 --- /dev/null +++ b/BehavioralPatterns/ChainOfReponsibility/README.md @@ -0,0 +1,61 @@ +# 职责链模式 Chain of Responsibility +## 意图 +通过设立有机会处理请求的中间对象,将请求的发起者和接受者解耦。链接这些接收对象、传递请求,直到该请求被处理。 + +经典的消息机制、异常处理都是这样一种职责链模式。发起的消息逐层向外传递,直到有处理该消息的对象出现。 + +## 适用性 +* 多个对象会处理请求,不同处理者间的优先级不明确,需要能够自动获知该由谁处理; +* 需要处理一类请求,可能来自不同对象,且没有显示地指明接受者; +* 能够处理请求的一组对象,能够被动态指定。 + +## 结构 + +![structure](./res/ChainOfResponsibilityStructure.png) + +典型的对象结构: + +![structure](./res/ChainOfResponsibilityObject.png) + +各部分角色的职责: + +* Handler + * 定义处理请求的接口 + * 实现继任者(successor)链接 +* ConcreteHandler + * 处理负责的请求 + * 如果不是其责任范围内的请求,负责将其传递给继任者 +* Client + * 面向的是ConcreteHandler + * 调用接口 + +## 模式效果 +1. 减少耦合 + + 对象只需要知道请求会被“妥善”处理,而不用关心是由谁处理;接受者无需知道请求的发起者;链式结构中的对象也无需了解整个链的结构。 + + 结果是,职责链模式简化了对象间的关联,对象无需维护请求的接受者的引用,只要持有后继者的引用即可。 +2. 分派责任更加灵活 + + 能够在运行时添加或修改对象所负担的责任。 +3. 请求不保证会被执行 + + 由于没有明确的责任对象,无法保证请求会最终被执行。也有可能由于职责链配置问题导致请求不被执行。 + +## 实现 +1. 实现继任者链有两种可行的方式: + * 定义新的链接(通常在Handler中,但ConcreteHandler需要重新定义) + * 使用已有的链接 + + 使用已有的继任者链接,意味着ConcreteHandler 创建时其继任者已经决定?这部分看得还不是太明白,需要之后结合代码再来看。 +2. 连接继任者 + + 如果没有已定义的链,就必须自己创建。这种情况下,Handler除了定义接口,还要定义继任者。 +3. 表达请求 + + 有多种表达请求的方式,最简单的,是硬编码,讲请求直接写在Handler中,缺点是扩展性不好。 + + 另一个选择是使用请求编号的方式(例如用一个整型值),根据编码决定如何请求。该做法要求发送者和接受者明确编码的含义。这一做法更为灵活,但需要额外的请求分发工作,而且不是类型安全。 + + 参数可用objects的方式,单独传输。 + diff --git a/BehavioralPatterns/ChainOfReponsibility/chain.py b/BehavioralPatterns/ChainOfReponsibility/chain.py new file mode 100644 index 000000000..6698f8f9e --- /dev/null +++ b/BehavioralPatterns/ChainOfReponsibility/chain.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://www.testingperspective.com/wiki/doku.php/collaboration/chetan/designpatternsinpython/chain-of-responsibilitypattern""" + +class Handler: + def __init__(self,successor): + self._successor = successor; + def handle(self,request): + i = self._handle(request) + if not i: + self._successor.handle(request) + def _handle(self, request): + raise NotImplementedError('Must provide implementation in subclass.') + + +class ConcreteHandler1(Handler): + + def _handle(self, request): + if 0 < request <= 10: + print('request {} handled in handler 1'.format(request)) + return True + +class ConcreteHandler2(Handler): + + def _handle(self, request): + if 10 < request <= 20: + print('request {} handled in handler 2'.format(request)) + return True + +class ConcreteHandler3(Handler): + + def _handle(self, request): + if 20 < request <= 30: + print('request {} handled in handler 3'.format(request)) + return True +class DefaultHandler(Handler): + + def _handle(self, request): + print('end of chain, no handler for {}'.format(request)) + return True + + +class Client: + def __init__(self): + self.handler = ConcreteHandler1(ConcreteHandler3(ConcreteHandler2(DefaultHandler(None)))) + def delegate(self, requests): + for request in requests: + self.handler.handle(request) + + +if __name__ == "__main__": + client = Client() + requests = [2, 5, 14, 22, 18, 3, 35, 27, 20] + client.delegate(requests) + +### OUTPUT ### +# request 2 handled in handler 1 +# request 5 handled in handler 1 +# request 14 handled in handler 2 +# request 22 handled in handler 3 +# request 18 handled in handler 2 +# request 3 handled in handler 1 +# end of chain, no handler for 35 +# request 27 handled in handler 3 +# request 20 handled in handler 2 diff --git a/BehavioralPatterns/ChainOfReponsibility/res/ChainOfResponsibilityObject.png b/BehavioralPatterns/ChainOfReponsibility/res/ChainOfResponsibilityObject.png new file mode 100644 index 0000000000000000000000000000000000000000..c3e1e87b7a70889f252beea0d353c0960b6e4d11 GIT binary patch literal 4608 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 literal 0 HcmV?d00001 From f9c8433744cf94125d5b061da13436f8efa38cce Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 26 May 2015 14:25:24 +0800 Subject: [PATCH 15/25] add facade pattern --- StructuralPatterns/Facade/README.md | 8 +++ StructuralPatterns/Facade/facade.py | 88 +++++++++++++++++++++++ StructuralPatterns/Facade/res/Facade.png | Bin 0 -> 4434 bytes 3 files changed, 96 insertions(+) create mode 100644 StructuralPatterns/Facade/README.md create mode 100644 StructuralPatterns/Facade/facade.py create mode 100644 StructuralPatterns/Facade/res/Facade.png diff --git a/StructuralPatterns/Facade/README.md b/StructuralPatterns/Facade/README.md new file mode 100644 index 000000000..1ccd2f454 --- /dev/null +++ b/StructuralPatterns/Facade/README.md @@ -0,0 +1,8 @@ +# 外观模式 Facade + +## 意图 +为子系统的一系列接口,提供一个统一的接口。外观模式为子系统提供了更高层级的接口调用,使系统更方便使用。 + +举一个例子,用户想要入手一台新电脑,他当然可以自己去挑选主板、内存、硬盘等,然后将这些组装起来(底层接口调用);也可以找一个懂行的人,帮自己去完成这些技术含量更高的工作(上层接口调用,此时这个被委托人就是一个Facade)。 + +## 适用性 diff --git a/StructuralPatterns/Facade/facade.py b/StructuralPatterns/Facade/facade.py new file mode 100644 index 000000000..77197dc30 --- /dev/null +++ b/StructuralPatterns/Facade/facade.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import time + +SLEEP = 0.5 + + +# Complex Parts +class TC1: + + def run(self): + print("###### In Test 1 ######") + time.sleep(SLEEP) + print("Setting up") + time.sleep(SLEEP) + print("Running test") + time.sleep(SLEEP) + print("Tearing down") + time.sleep(SLEEP) + print("Test Finished\n") + + +class TC2: + + def run(self): + print("###### In Test 2 ######") + time.sleep(SLEEP) + print("Setting up") + time.sleep(SLEEP) + print("Running test") + time.sleep(SLEEP) + print("Tearing down") + time.sleep(SLEEP) + print("Test Finished\n") + + +class TC3: + + def run(self): + print("###### In Test 3 ######") + time.sleep(SLEEP) + print("Setting up") + time.sleep(SLEEP) + print("Running test") + time.sleep(SLEEP) + print("Tearing down") + time.sleep(SLEEP) + print("Test Finished\n") + + +# Facade +class TestRunner: + + def __init__(self): + self.tc1 = TC1() + self.tc2 = TC2() + self.tc3 = TC3() + self.tests = [i for i in (self.tc1, self.tc2, self.tc3)] + + def runAll(self): + [i.run() for i in self.tests] + + +# Client +if __name__ == '__main__': + testrunner = TestRunner() + testrunner.runAll() + +### OUTPUT ### +# ###### In Test 1 ###### +# Setting up +# Running test +# Tearing down +# Test Finished +# +# ###### In Test 2 ###### +# Setting up +# Running test +# Tearing down +# Test Finished +# +# ###### In Test 3 ###### +# Setting up +# Running test +# Tearing down +# Test Finished +# diff --git a/StructuralPatterns/Facade/res/Facade.png b/StructuralPatterns/Facade/res/Facade.png new file mode 100644 index 0000000000000000000000000000000000000000..42cc641d770eaa4a3dbcc7571dea19d1b77a1f60 GIT binary patch literal 4434 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 literal 0 HcmV?d00001 From f7d57b203484ef1b6c862a3fe153285367832303 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 26 May 2015 14:45:10 +0800 Subject: [PATCH 16/25] update --- StructuralPatterns/Facade/README.md | 32 ++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/StructuralPatterns/Facade/README.md b/StructuralPatterns/Facade/README.md index 1ccd2f454..444ae8edb 100644 --- a/StructuralPatterns/Facade/README.md +++ b/StructuralPatterns/Facade/README.md @@ -5,4 +5,34 @@ 举一个例子,用户想要入手一台新电脑,他当然可以自己去挑选主板、内存、硬盘等,然后将这些组装起来(底层接口调用);也可以找一个懂行的人,帮自己去完成这些技术含量更高的工作(上层接口调用,此时这个被委托人就是一个Facade)。 -## 适用性 +## 适用范围 +* 希望对一个复杂的子系统提供简单的接口,用户主需要面向这一外观即可访问子系统; +* 用户调用一个抽象的实现时会涉及到许多的依赖,通过外观实现解耦; +* 希望将子系统层级化,使用外观模式来定义每个层级的入口。如果各个子系统是独立的,可以使用外观作为他们之间的交互接口 + +## 结构 + +![structure](./res/Facade.png) + +外观模式的结构非常灵活,只要是通过Facade访问子系统就可以,其内部具体是如何调用没有限制。 + +## 模式效果 + +1. 将用户和子系统隔离,减少了用户需要处理的对象,简化了子系统的使用; +2. 使用户和子系统之间松耦合。松耦合使得子系统内部成员变化时不会影响用户。 +3. 在必要的情况下,外观模式并不阻止直接使用子系统的类,由用户决定是要易用性,还是通用性。 + +## 实现 +实现外观模式时,需要考虑以下一些因素 + +1. 减少用户-系统之间的耦合。 + + 除了外观模式本身的松耦合特性,更进一步的做法是创建Facade抽象类,对于不同的子系统实现具体的Facade子类。用户通过Facade基类的接口与子系统交互。这一做法使得用户无需了解当前使用的是哪个子类的实现。 + + 另一种方法是为Facade配置不同的子类对象(类似策略模式),通过替换子系统对象来定制Facade。 + +2. 公有还是私有的子系统类? + + 子系统可以和类进行类比,他们同样包含接口,同样封装内容——类封装状态和方法,子系统封装类。就像设置类的访问控制一样,我们可以考虑子系统接口究竟是公开的,还是私有的。 + + 公有的接口是所有用户都能访问的,私有接口是仅对内部类开放的。Facade肯定是一个公有的接口,但不是唯一的一个,子系统中的其他接口也可以是公有的,有通用性需求的用户可以访问。 \ No newline at end of file From 43eedb2c82acdb40b728750b7c620fb212848bf8 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 26 May 2015 17:28:34 +0800 Subject: [PATCH 17/25] add proxy pattern --- StructuralPatterns/Proxy/README.md | 38 +++++++++++++++++++++++++ StructuralPatterns/Proxy/res/Proxy.png | Bin 0 -> 9418 bytes 2 files changed, 38 insertions(+) create mode 100644 StructuralPatterns/Proxy/README.md create mode 100644 StructuralPatterns/Proxy/res/Proxy.png diff --git a/StructuralPatterns/Proxy/README.md b/StructuralPatterns/Proxy/README.md new file mode 100644 index 000000000..8831d84fe --- /dev/null +++ b/StructuralPatterns/Proxy/README.md @@ -0,0 +1,38 @@ +# 代理模式 Proxy + +## 意图 +为对象提供代理或占位符,实现访问控制。除了Proxy,也被称为Surrogate。 + +需要访问控制的其中一个理由是,延迟对象的创建和初始化,直到我们真的需要使用它。例如有一个包含了很多图片的文档,如果在打开时就将所有的图片都加载到内存中,那文档打开就会非常迟缓,这时候就可以用一个图片代理对象来替换真实的图片。图片代理有着图片的一些基本信息,例如长和宽,也有着如何找到这张图片的引用,例如URL。只有到需要显示这些图片时,才会去尝试通过引用加载图片。 + +## 使用范围 + +当需要一个相比于指针更为通用、复杂的引用,来指代对象时,通常会考虑使用代理模式,以下是一些使用的场景: + +1. 远程代理(**remote proxy**)提供了不同地址空间中对象的本地代表。 +2. 虚拟代理(**virtual proxy**)为初始化开销大的对象设置代理,延迟创建对象。 +3. 保护代理(**protection proxy**)管控原始对象的访问权限。当对象对于不同用户提供不同访问权限时,这类代理很有用。 +4. 智能引用(**smart reference**)是裸指针的一个替代,当对象被访问时会有一些额外行为,典型的使用包括: + * 引用计数 + * 首次引用时负责将加载对象 + * 当对象被访问时检查是否被锁 + +## 结构 + +![structure](./res/Proxy.png) + +## 模式效果 + +1. 远程代理屏蔽了对象其实是不同地址空间的事实; +2. 虚拟代理优化了对象加载; +3. 保护代理和智能引用都在对象访问时添加了额外的管理功能; + +另一种使用代理模式优化的做法,称为**copy-on-write**。拷贝一个复杂的大对象开销很大,如果这一拷贝从未被修改,那就没有必要去真正地拷贝。通过使用代理模式延迟拷贝的过程,确保只有在被修改后才执行拷贝操作。 + +上述操作要求对象进行引用计数,拷贝时引用计数+1,修改时引用计数-1并进行拷贝和修改,引用计数减为0时删除对象。 + +## 实现 + +1. 使用C++实现时,重载成员访问操作符(->) + + 每当对象被接触引用,重载该操作符使你能执行额外的工作,通过重载操作符,代理就能像指针一样地使用。 \ No newline at end of file diff --git a/StructuralPatterns/Proxy/res/Proxy.png b/StructuralPatterns/Proxy/res/Proxy.png new file mode 100644 index 0000000000000000000000000000000000000000..e39419d22ef3aa075a254aecda212ebe848e9e5c GIT binary patch literal 9418 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 Date: Tue, 26 May 2015 17:29:40 +0800 Subject: [PATCH 18/25] proxy update --- StructuralPatterns/Proxy/proxy.py | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 StructuralPatterns/Proxy/proxy.py diff --git a/StructuralPatterns/Proxy/proxy.py b/StructuralPatterns/Proxy/proxy.py new file mode 100644 index 000000000..4c5b4cc04 --- /dev/null +++ b/StructuralPatterns/Proxy/proxy.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import time + + +class SalesManager: + + def work(self): + print("Sales Manager working...") + + def talk(self): + print("Sales Manager ready to talk") + + +class Proxy: + + def __init__(self): + self.busy = 'No' + self.sales = None + + def work(self): + print("Proxy checking for Sales Manager availability") + if self.busy == 'No': + self.sales = SalesManager() + time.sleep(2) + self.sales.talk() + else: + time.sleep(2) + print("Sales Manager is busy") + + +if __name__ == '__main__': + p = Proxy() + p.work() + p.busy = 'Yes' + p.work() + +### OUTPUT ### +# Proxy checking for Sales Manager availability +# Sales Manager ready to talk +# Proxy checking for Sales Manager availability +# Sales Manager is busy From b0d1f3e413711b3a5937117f81259f70356c2e4a Mon Sep 17 00:00:00 2001 From: luchengchao Date: Wed, 27 May 2015 12:27:45 +0800 Subject: [PATCH 19/25] add command pattern --- BehavioralPatterns/Command/README.md | 50 +++++++++++++++++++++ BehavioralPatterns/Command/command.py | 44 ++++++++++++++++++ BehavioralPatterns/Command/res/Command.png | Bin 0 -> 11093 bytes 3 files changed, 94 insertions(+) create mode 100644 BehavioralPatterns/Command/README.md create mode 100644 BehavioralPatterns/Command/command.py create mode 100644 BehavioralPatterns/Command/res/Command.png diff --git a/BehavioralPatterns/Command/README.md b/BehavioralPatterns/Command/README.md new file mode 100644 index 000000000..900253bc0 --- /dev/null +++ b/BehavioralPatterns/Command/README.md @@ -0,0 +1,50 @@ +# 命令模式 Command + +## 意图 +将请求封装成对象,由此可用不同的请求作为参数,将请求队列化,日志输出请求,还支持操作的回退。 + +也被称为动作模式(Action)、事务模式(Transaction)。 + +## 适用性 +当你有以下需求时使用命令模式 + +* 将动作执行参数化。命令模式就是回调函数的面向对象的替代。 +* 描述请求、队列缓存请求、不在请求创建时执行请求。 +* 支持回退操作,这要求命令对象除了执行操作外,还提供回退操作的接口。 +* 支持输出请求变化日志,当系统奔溃后能够从断点恢复执行。数据库一般都有类似的操作日志。 +* 在底层操作的基础上使用上层操作构建系统。典型的应用就是数据库操作中的事务(Transaction)。每个事务都包括多个基本的操作,当所有操作都成功后事务才提交,否则回退所有的操作。 + +## 结构 + +![structure](./res/Command.png) + +其中,Client的责任是创建ConcreteCommand,并为其指定Receiver。 + +## 模式效果 + +1. 命令模式将对象调用执行和如何执行解耦。 +2. 命令是一级对象,这意味着能够像其他对象一样操作、扩展。 +3. 可以讲多个命令集成为一个复合命令。 +4. 很容易添加新的命令,因为这不会影响已有的类。 + +## 实现 +实现命令模式时需要考虑以下一些问题: + +1. 命令该有多智能? + + 一个极端是仅仅提供了receiver,用来调用请求,另一个极端是完全不管receiver,在命令中将请求实现。 + +2. 支持回退和重新执行 + + 除了提供相应的接口,ConcreteCommand类还需要存储额外的状态,可能包括: + + * 接收请求的对象 + * 操作执行的参数 + * 接收对象的原始状态,确保能够让接受者回退到上一状态 + + 一级回退,只要存储上个命令;多级回退就需要存储历史命令列表。 + + 一个可回退的命令必须支持拷贝,因为需要拷贝到历史命令列表中,而不能仅仅是存储命令的引用,因为命令可能会被修改。 + +3. 在回退操作时避免出现错误累积情况 +4. 考虑使用C++的模板实现 \ No newline at end of file diff --git a/BehavioralPatterns/Command/command.py b/BehavioralPatterns/Command/command.py new file mode 100644 index 000000000..727f42cbf --- /dev/null +++ b/BehavioralPatterns/Command/command.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + + +class MoveFileCommand(object): + + def __init__(self, src, dest): + self.src = src + self.dest = dest + + def execute(self): + print('renaming {} to {}'.format(self.src, self.dest)) + os.rename(self.src, self.dest) + + def undo(self): + print('renaming {} to {}'.format(self.dest, self.src)) + os.rename(self.dest, self.src) + + +def main(): + command_stack = [] + + # commands are just pushed into the command stack + command_stack.append(MoveFileCommand('foo.txt', 'bar.txt')) + command_stack.append(MoveFileCommand('bar.txt', 'baz.txt')) + + # they can be executed later on + for cmd in command_stack: + cmd.execute() + + # and can also be undone at will + for cmd in reversed(command_stack): + cmd.undo() + +if __name__ == "__main__": + main() + +### OUTPUT ### +# renaming foo.txt to bar.txt +# renaming bar.txt to baz.txt +# renaming baz.txt to bar.txt +# renaming bar.txt to foo.txt diff --git a/BehavioralPatterns/Command/res/Command.png b/BehavioralPatterns/Command/res/Command.png new file mode 100644 index 0000000000000000000000000000000000000000..003b44fca6bf619fabffed1c06dbd040b80d095f GIT binary patch literal 11093 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 literal 0 HcmV?d00001 From 2b30dbbcc4def77e3f7ef14eacdf1f8083a4b769 Mon Sep 17 00:00:00 2001 From: luchengchao Date: Mon, 1 Jun 2015 15:14:29 +0800 Subject: [PATCH 20/25] add interpreter pattern --- BehavioralPatterns/Interpreter/README.md | 54 ++++++++++++++++++ .../Interpreter/res/Interpreter.png | Bin 0 -> 10519 bytes 2 files changed, 54 insertions(+) create mode 100644 BehavioralPatterns/Interpreter/README.md create mode 100644 BehavioralPatterns/Interpreter/res/Interpreter.png diff --git a/BehavioralPatterns/Interpreter/README.md b/BehavioralPatterns/Interpreter/README.md new file mode 100644 index 000000000..e4276efec --- /dev/null +++ b/BehavioralPatterns/Interpreter/README.md @@ -0,0 +1,54 @@ +# 解释器模式 Interpreter + +## 意图 +定义语言的语法,并能够使用该语法解释该语言中的句子。 + +## 适用性 +当有一种语言需要翻译,而且能将该语言中的语句用抽象的语法树表示时,可以使用解释器模式。解释器模式在以下情况下运行得最好: + +* 语法简单 + + 复杂的语法就需要复杂的、庞大的、难以管理的类结构。对于这种情况使用像解析生成器(parser generator)这样的工具是一种替代方案,它能够在不创建抽象语法树的前提实现解释语言,能够节省空间和时间。 + +* 效率不是主要的考量 + + 最高效的解释器通常不是通过解释器实现,而是将它们转化成另一种形式。 + +## 结构 + +![structure](./res/Interpreter.png) + +解释器的核心,就是建立这样一个语法树,用户直接面向抽线基类,调用解释方法翻译内容。 + +## 模式效果 + +1. 方便修改和扩展语法。 + + 修改现有类实现修改语法,通过新增类实现扩展语法。 + +2. 实现语法也容易 + + 语法树中的大部分结点代码都比较类似,实现了一个之后其他差不多也都有了。 + +3. 复杂的语法难以维护 + + 在解释器模式中,至少有一个类需要了解语言中所有的语法,所以如果有许多规则,就很难管理和维护。当语法复杂时,其他的技术,例如解析器(parser)、编译器(compiler)就更为合适。 + +4. 添加新的方式来解释表达式 + + 通过解释器模式,能够方便地为表达式提供新的评估方式。例如,对一个语句以更为漂亮的方式输出。如果你持续创建新的解释方式,建议使用访问者模式(Visitor)。 + +## 实现 +解释器模式和组合模式实现时有很多相似之处,下面是一些解释器模式特有的话题: + +1. 创建抽象语法树。 + + 对于抽象语法树的创建方式,解释器模式没有硬性规定。具体问题具体分析。 +2. 定义解释器的操作 + + 不需要在表达式类(Expression class)中定义解释器的操作,通常将新创建的解释器,放在访问者对象中。 +3. 使用蝇量模式共享最小符号 + + 语法中会有许多基本的最小符号(例如英语中的字母,算数运算中的加减乘除符号),能通过蝇量模式共享资源从而获益。 + + 最小结点通常不会存储他们在抽象语法树中的位置,由父节点负责提供上下文信息。这就涉及到蝇量模式中的一个概念:内部状态和外部状态。 \ No newline at end of file diff --git a/BehavioralPatterns/Interpreter/res/Interpreter.png b/BehavioralPatterns/Interpreter/res/Interpreter.png new file mode 100644 index 0000000000000000000000000000000000000000..f762a5f458cb0976bf2300b1007a001d87c81ca4 GIT binary patch literal 10519 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 literal 0 HcmV?d00001 From d0f263979be6be400f593db9c26e6fc9ae310efb Mon Sep 17 00:00:00 2001 From: luchengchao Date: Tue, 2 Jun 2015 16:19:15 +0800 Subject: [PATCH 21/25] add iterator pattern --- BehavioralPatterns/Iterator/README.md | 74 +++++++++++++++++++ BehavioralPatterns/Iterator/iterator.py | 37 ++++++++++ BehavioralPatterns/Iterator/res/Iterator.png | Bin 0 -> 13446 bytes 3 files changed, 111 insertions(+) create mode 100644 BehavioralPatterns/Iterator/README.md create mode 100644 BehavioralPatterns/Iterator/iterator.py create mode 100644 BehavioralPatterns/Iterator/res/Iterator.png diff --git a/BehavioralPatterns/Iterator/README.md b/BehavioralPatterns/Iterator/README.md new file mode 100644 index 000000000..2aead4f57 --- /dev/null +++ b/BehavioralPatterns/Iterator/README.md @@ -0,0 +1,74 @@ +# 迭代器模式 +## 意图 +提供一种顺序访问对象集合的方法,而不用关心其底层实现。 + +也成为游标(Cursor)。 + +## 适用性 + +* 不暴露内部表现的情况下,访问一个集合对象; +* 支持对集合对象的多重遍历; +* 为遍历不同的集合结构,提供统一的接口; + +## 结构 + +![structure](./res/Iterator.png) + +创建迭代器,需要调用集合中的接口。 + +## 模式效果 + +1. 支持集合遍历方式的变化 + + 复杂的集合可能会以多种方式遍历,迭代器模式使得变更迭代算法变得简单,只需要用一个新的迭代器实例替换当前的即可。 +2. 迭代器简化了集合的接口 + + 集合本身有遍历的需求,通过迭代器来实现了这些功能,集合的接口就得以简化。 +3. 集合可以有多种遍历方法 + + 集合的遍历状态,由迭代器维护,因此集合同时可以有多个遍历。 + +## 实现 +迭代器有许多的实现变化和选择,其中的取舍往往是依赖于实现的语言。下面是一些重要的方面: + +1. 谁控制迭代? + + 是由迭代器还是客户控制迭代?当用户控制迭代,称为外部迭代器,如果由迭代器自身控制,称为内部迭代器。 + + 外部迭代器比内部迭代器更为灵活,能够简单地比较对象相等。内部迭代器对于像C++这样没有匿名函数、闭包的语言,不是很有意义,但使用起来很方便,因为迭代逻辑集成在迭代器中。 +2. 谁定义遍历算法? + + 并非只有迭代器可以定义遍历算法,集合本身也可以定义遍历算法,迭代器只是用来存储迭代的状态。将这种迭代器称为**游标**,因为它仅仅用来指向集合中的当前位置。 + + 如果由迭代器定义遍历算法,就很方便对同一个集合使用不同的遍历算法,也可以将同样的遍历算法用到不同的集合上。反之,由于遍历算法会访问集合的私有成员,会破坏集合的封装。 +3. 迭代器的鲁棒性如何? + + 迭代时修改集合非常危险,可能会访问同一对象两次,也可能错过某个对象。简单的解决方案是遍历集合的拷贝,但这样做代价太高。 + + 一个鲁棒性好的迭代器需要确保插入和删除时不会干扰迭代,而且不用拷贝集合 +4. 额外的迭代器操作 + + 除了上述的迭代器基本操作,还有一些额外的操作,也很有用。例如,有序集合有Previous操作访问前一个元素;对于已排序的或已索引的集合SkipTo操作也很有用。 +5. C++中使用多态迭代器 + + 多态迭代器的对象是通过工厂方法动态创建的,只有在支持多态时才使用,否则就用具体迭代器,在栈上分配。 + + 多态迭代器还有一个缺点:用户需要负责删除对象,很多时候用户都会忘记释放堆上的对象,尤其是当操作有多个出口点时。 + + 代理模式提供了弥补方案。可以使用在栈上分配的代理作为实际迭代器的替身,在代理的析构中释放迭代器。当代理离开作用域时,迭代器也被一并释放。即使在发生异常时,代理也能清理干净堆上的资源。这是C++为人熟知的技术“资源分配即初始化(resource allocation is initialization)”。 +6. 迭代器的访问特权 + + 迭代器可以被看成是集合的扩展,两者是紧耦合的,在C++中,可以将迭代器设置为集合的友元,这样迭代器就能直接访问集合属性,是遍历更为高效。 + + 然而,这种访问特权会使定义新的遍历变得困难,因为要求集合定义新的友元。为了避免这一情况,迭代器可以包含保护方法(protected operation)访问集合的非公开但核心的成员,迭代器的子类(且仅是子类)可以通过这些方法访问集合。 +7. 组合的迭代器 + + 外部迭代器想要实现对迭代形式的组合集合进行遍历,会比较困难,因为集合结构中的位置可能是许多层级的嵌套,因此外部迭代器需要记录下组合位置的完整路径。使用内部迭代器就比较方便,因为组合中的对象能够方便地掌握自己的当前位置。 + + 如果组合中的结点支持移动,那游标型的迭代器是更好的选择,只需要保存当前结点的追踪。 + + 组合通常需要多种迭代方式,前序、后序等,可通过不同迭代器类实现各种遍历方式。 +8. 空迭代器 + + 空迭代器是一个退化的迭代器,用来判断边界条件时很有用。通过定义,空迭代器总是遍历的完成,调用IsDone的结果总是true。 +9. diff --git a/BehavioralPatterns/Iterator/iterator.py b/BehavioralPatterns/Iterator/iterator.py new file mode 100644 index 000000000..3aa36b8d4 --- /dev/null +++ b/BehavioralPatterns/Iterator/iterator.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ + +Implementation of the iterator pattern with a generator""" + + +def count_to(count): + """Counts by word numbers, up to a maximum of five""" + numbers = ["one", "two", "three", "four", "five"] + # enumerate() returns a tuple containing a count (from start which + # defaults to 0) and the values obtained from iterating over sequence + for pos, number in zip(range(count), numbers): + yield number + +# Test the generator +count_to_two = lambda: count_to(2) +count_to_five = lambda: count_to(5) + +print('Counting to two...') +for number in count_to_two(): + print(number, end=' ') + +print() + +print('Counting to five...') +for number in count_to_five(): + print(number, end=' ') + +print() + +### OUTPUT ### +# Counting to two... +# one two +# Counting to five... +# one two three four five diff --git a/BehavioralPatterns/Iterator/res/Iterator.png b/BehavioralPatterns/Iterator/res/Iterator.png new file mode 100644 index 0000000000000000000000000000000000000000..f058e77a87e7785db945eca59d47cd55c7d8fb1b GIT binary patch literal 13446 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 Date: Wed, 3 Jun 2015 09:48:02 +0800 Subject: [PATCH 22/25] add mediator pattern --- BehavioralPatterns/Mediator/README.md | 57 +++++++ BehavioralPatterns/Mediator/mediator.py | 143 ++++++++++++++++++ .../Mediator/res/MediatorSample.png | Bin 0 -> 17525 bytes .../Mediator/res/MediatorStructure.png | Bin 0 -> 6425 bytes 4 files changed, 200 insertions(+) create mode 100644 BehavioralPatterns/Mediator/README.md create mode 100644 BehavioralPatterns/Mediator/mediator.py create mode 100644 BehavioralPatterns/Mediator/res/MediatorSample.png create mode 100644 BehavioralPatterns/Mediator/res/MediatorStructure.png diff --git a/BehavioralPatterns/Mediator/README.md b/BehavioralPatterns/Mediator/README.md new file mode 100644 index 000000000..6adf5701c --- /dev/null +++ b/BehavioralPatterns/Mediator/README.md @@ -0,0 +1,57 @@ +# 中介者模式 Mediator + +## 意图 +定义一个对象,封装一系列对象的交互。中介者模式推崇松耦合,防止对象显示地互相引用,通过中介者能独立地切换交互方式。 + +## 适用性 + +在以下情况时考虑使用中介者模式: + +* 一系列对象间的交互定义得非常清晰,但又非常复杂 +* 复用对象困难因为它引用了许多其他对象 +* 在多个类之间的分发行为,不需要引入很多子类,就能够实现。 + +## 结构 + +![structure](./res/MediatorStructure.png) + +这个结构比较抽象,添加一个具体的实例: +![structure](./res/MediatorSample.png) + +其中DialogDirector相当于Mediator,FontDialogDirector相当于ConcreteMediator。当任何一个Widget有变化时,会通过WidgetChanged方法通知Mediator,Mediator再对相关的Widget进行更新。这样做将一系列的Widget从交互中解脱,统一和Mediator进行。 + +## 模式效果 + +中介者模式有以下一些好处和不足: + +1. 限制了继承的泛滥 + + 中介者实现了原本要在多个对象互相交互的行为,变更行为只需要实现子类继承中介者,同僚类(Colleague)可以复用。 +2. 解耦了各同僚 + + 中介者模式使同僚之间松耦合,很方便变化和复用各同僚和中介者。 +3. 简化了对象协议 + + 中介者模式将多对多的协议简化为了一对多,这更有利于理解、维护和扩展。 +4. 抽象了对象的协作方式 + + 将中间件独立开来,开发时能够专注在业务对象本身。 +5. 集中控制 + + 将同僚之间的复杂度转化为中介者内部的复杂度。因为中介者封装了协议,变得比其他对象更为复杂,这使得中介者本身更加难以维护。 + +## 实现 + +1. 忽略抽象的中介者类 + + 当系统中只存在一个中介者时,可忽略抽象的中介者类,只有在多个中介者的情况下抽象类才有意义。 +2. 同僚与中介者通信 + + 当有中介者关心的事件发生时,同僚需要发起通信,可以使用观察者模式来实现这一功能。将中介者视为观察者,将同僚类设为主题。 + + 另一种方式是在中介者中定义一个通知接口,需要发起通信时调用该接口。 + +## 模式思考 +与外观模式相比,有一个显著的特点是中介者封装的是一个系列的对象(a set of objects),这些对象彼此之间有着潜在的联系,这一概念和工厂模式的核心“簇”(Family)有点相似。 + +另一方面,Facade封装了子系统对外的接口,而Mediator对于系列中对象之间的访问也进行了封装,使得这些对象也只和Mediator交互。 \ No newline at end of file diff --git a/BehavioralPatterns/Mediator/mediator.py b/BehavioralPatterns/Mediator/mediator.py new file mode 100644 index 000000000..82a2886fa --- /dev/null +++ b/BehavioralPatterns/Mediator/mediator.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://dpip.testingperspective.com/?p=28""" + +import random +import time + + +class TC: + + def __init__(self): + self._tm = None + self._bProblem = 0 + + def setup(self): + print("Setting up the Test") + time.sleep(0.1) + self._tm.prepareReporting() + + def execute(self): + if not self._bProblem: + print("Executing the test") + time.sleep(0.1) + else: + print("Problem in setup. Test not executed.") + + def tearDown(self): + if not self._bProblem: + print("Tearing down") + time.sleep(0.1) + self._tm.publishReport() + else: + print("Test not executed. No tear down required.") + + def setTM(self, tm): + self._tm = tm + + def setProblem(self, value): + self._bProblem = value + + +class Reporter: + + def __init__(self): + self._tm = None + + def prepare(self): + print("Reporter Class is preparing to report the results") + time.sleep(0.1) + + def report(self): + print("Reporting the results of Test") + time.sleep(0.1) + + def setTM(self, tm): + self._tm = tm + + +class DB: + + def __init__(self): + self._tm = None + + def insert(self): + print("Inserting the execution begin status in the Database") + time.sleep(0.1) + # Following code is to simulate a communication from DB to TC + if random.randrange(1, 4) == 3: + return -1 + + def update(self): + print("Updating the test results in Database") + time.sleep(0.1) + + def setTM(self, tm): + self._tm = tm + + +class TestManager: + + def __init__(self): + self._reporter = None + self._db = None + self._tc = None + + def prepareReporting(self): + rvalue = self._db.insert() + if rvalue == -1: + self._tc.setProblem(1) + self._reporter.prepare() + + def setReporter(self, reporter): + self._reporter = reporter + + def setDB(self, db): + self._db = db + + def publishReport(self): + self._db.update() + self._reporter.report() + + def setTC(self, tc): + self._tc = tc + + +if __name__ == '__main__': + reporter = Reporter() + db = DB() + tm = TestManager() + tm.setReporter(reporter) + tm.setDB(db) + reporter.setTM(tm) + db.setTM(tm) + # For simplification we are looping on the same test. + # Practically, it could be about various unique test classes and their + # objects + for i in range(3): + tc = TC() + tc.setTM(tm) + tm.setTC(tc) + tc.setup() + tc.execute() + tc.tearDown() + +### OUTPUT ### +# Setting up the Test +# Inserting the execution begin status in the Database +# Executing the test +# Tearing down +# Updating the test results in Database +# Reporting the results of Test +# Setting up the Test +# Inserting the execution begin status in the Database +# Reporter Class is preparing to report the results +# Problem in setup. Test not executed. +# Test not executed. No tear down required. +# Setting up the Test +# Inserting the execution begin status in the Database +# Executing the test +# Tearing down +# Updating the test results in Database +# Reporting the results of Test diff --git a/BehavioralPatterns/Mediator/res/MediatorSample.png b/BehavioralPatterns/Mediator/res/MediatorSample.png new file mode 100644 index 0000000000000000000000000000000000000000..800778471e3ecd643ef6147ba36f8a73dbca3ad5 GIT binary patch literal 17525 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 Dddr^r literal 0 HcmV?d00001 diff --git a/BehavioralPatterns/Mediator/res/MediatorStructure.png b/BehavioralPatterns/Mediator/res/MediatorStructure.png new file mode 100644 index 0000000000000000000000000000000000000000..4789bf04a47445866a8346abf4766c4b9ff9808c GIT binary patch literal 6425 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 Date: Wed, 3 Jun 2015 11:56:00 +0800 Subject: [PATCH 23/25] add memento pattern --- BehavioralPatterns/Memento/README.md | 45 ++++++++ BehavioralPatterns/Memento/memento.py | 127 +++++++++++++++++++++ BehavioralPatterns/Memento/res/Memento.png | Bin 0 -> 11289 bytes 3 files changed, 172 insertions(+) create mode 100644 BehavioralPatterns/Memento/README.md create mode 100644 BehavioralPatterns/Memento/memento.py create mode 100644 BehavioralPatterns/Memento/res/Memento.png diff --git a/BehavioralPatterns/Memento/README.md b/BehavioralPatterns/Memento/README.md new file mode 100644 index 000000000..8928f9689 --- /dev/null +++ b/BehavioralPatterns/Memento/README.md @@ -0,0 +1,45 @@ +# 备忘录模式 Memento + +## 意图 +不破化原有的封装,获取对象的内部状态并记录,使得对象在将来能够回退到这一记录的状态。 + +也被称为Token。 + +## 适用性 + +* 需要存储对象状态(至少是部分状态)的快照,用来在未来某些情况下回退对象; +* 通过直接接口访问的方式获取状态会暴露对象的实现细节,破坏对象的封装; + +## 结构 + +![structure](./res/Memento.png) + +Memento对于Caretaker只开放**窄接口**——Caretaker只存储和传递Memento,但不能访问其中的state(如何实现?private方法+设置Originator为友元?),对于Originator开放**宽接口**——能够访问state。 + +## 模式效果 + +1. 保护已有封装 + + 备忘录模式避免了暴露仅有发起人管理、但又必须存储在外部的信息。 +2. 简化了发起人 + + 其他设计方案中,发起人必须自己保存快照信息。使用备忘录模式后,快照信息存储在发起人的外部,简化了本身对象。 +3. 使用备忘录的代价可能会较高 + + 如果发起者每次快照需要记录大量信息、或是用户使用快照的过于频繁,备忘录模式可能会导致相当可观的维护开销。尽量确保发起者需要回退的状态轻量级情况。 +4. 定义窄接口和宽接口 + + 宽窄接口的说明在结构章节中提到,这一需求在部分语言中较难实现。 +5. 维护备忘录时的隐藏开销 + + Caretaker负责维护备忘录(包括删除),但它并不了解备忘录中包含多少状态信息,因此一个轻量级的Caretaker可能会因为维护大量备忘录而占用大量存储。 + +## 实现 +有以下两个话题需要考虑 + +1. 语言的支持 + + 备忘录模式需要宽窄两种接口,理想情况下实现语言要支持两层的静态保护。C++中,你可以将*宽接口设为私有*,然后将发起人设为友元,将窄接口设为公开。 +2. 存储变化增量 + + 当备忘录按照一个可预测的顺序创建和传回时,可以只存储发起人内部状态的增量信息 \ No newline at end of file diff --git a/BehavioralPatterns/Memento/memento.py b/BehavioralPatterns/Memento/memento.py new file mode 100644 index 000000000..42034658a --- /dev/null +++ b/BehavioralPatterns/Memento/memento.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""http://code.activestate.com/recipes/413838-memento-closure/""" + +import copy + + +def Memento(obj, deep=False): + state = (copy.copy, copy.deepcopy)[bool(deep)](obj.__dict__) + + def Restore(): + obj.__dict__.clear() + obj.__dict__.update(state) + return Restore + + +class Transaction: + + """A transaction guard. This is really just + syntactic suggar arount a memento closure. + """ + deep = False + + def __init__(self, *targets): + self.targets = targets + self.Commit() + + def Commit(self): + self.states = [Memento(target, self.deep) for target in self.targets] + + def Rollback(self): + for st in self.states: + st() + + +class transactional(object): + + """Adds transactional semantics to methods. Methods decorated with + @transactional will rollback to entry state upon exceptions. + """ + + def __init__(self, method): + self.method = method + + def __get__(self, obj, T): + def transaction(*args, **kwargs): + state = Memento(obj) + try: + return self.method(obj, *args, **kwargs) + except: + state() + raise + return transaction + + +class NumObj(object): + + def __init__(self, value): + self.value = value + + def __repr__(self): + return '<%s: %r>' % (self.__class__.__name__, self.value) + + def Increment(self): + self.value += 1 + + @transactional + def DoStuff(self): + self.value = '1111' # <- invalid value + self.Increment() # <- will fail and rollback + + +if __name__ == '__main__': + n = NumObj(-1) + print(n) + t = Transaction(n) + try: + for i in range(3): + n.Increment() + print(n) + t.Commit() + print('-- commited') + for i in range(3): + n.Increment() + print(n) + n.value += 'x' # will fail + print(n) + except: + t.Rollback() + print('-- rolled back') + print(n) + print('-- now doing stuff ...') + try: + n.DoStuff() + except: + print('-> doing stuff failed!') + import sys + import traceback + traceback.print_exc(file=sys.stdout) + pass + print(n) + +### OUTPUT ### +# +# +# +# +# -- commited +# +# +# +# -- rolled back +# +# -- now doing stuff ... +# -> doing stuff failed! +# Traceback (most recent call last): +# File "memento.py", line 91, in +# n.DoStuff() +# File "memento.py", line 47, in transaction +# return self.method(obj, *args, **kwargs) +# File "memento.py", line 67, in DoStuff +# self.Increment() # <- will fail and rollback +# File "memento.py", line 62, in Increment +# self.value += 1 +# TypeError: Can't convert 'int' object to str implicitly +# diff --git a/BehavioralPatterns/Memento/res/Memento.png b/BehavioralPatterns/Memento/res/Memento.png new file mode 100644 index 0000000000000000000000000000000000000000..57e205b89bd73001fba74f3314683ae7ca30b557 GIT binary patch literal 11289 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 Date: Thu, 4 Jun 2015 09:43:18 +0800 Subject: [PATCH 24/25] add visitor pattern --- BehavioralPatterns/Visitor/README.md | 69 ++++++++++++++++++ .../Visitor/res/VisitorObject.png | Bin 0 -> 10960 bytes .../Visitor/res/VisitorStructure.png | Bin 0 -> 22158 bytes 3 files changed, 69 insertions(+) create mode 100644 BehavioralPatterns/Visitor/README.md create mode 100644 BehavioralPatterns/Visitor/res/VisitorObject.png create mode 100644 BehavioralPatterns/Visitor/res/VisitorStructure.png diff --git a/BehavioralPatterns/Visitor/README.md b/BehavioralPatterns/Visitor/README.md new file mode 100644 index 000000000..731838192 --- /dev/null +++ b/BehavioralPatterns/Visitor/README.md @@ -0,0 +1,69 @@ +# 访问者模式 Visitor + +## 意图 +封装一些施加于某种数据结构元素之上的操作。访问者使你能够在不修改操作元素的类的情况下定义新的操作。 + +## 适用性 + +* 一个数据结构中包含许多类,有着不同的接口,希望根据不同的类执行不同的操作。 +* 对象会执行许多不同且没有关联的操作,你不希望对象的类被这么多操作锁“污染”。访问者让你将相关的操作定义在一个类中。 +* 数据结构中的类很少发生变化,但会对整体机构定义新的操作,修改数据结构中类的接口会影响所有的访问者,代价高昂,如果数据结构中类变化频繁,最好将这些类定义在访问者中 + +## 结构 + +![structure](./res/VisitorStructure.png) + +从结构定义中能够看出,抽象访问者中定义了所有ConcreteElement的访问方法,所以整个结构中的Element要尽可能固定。 + +## 协作流程 + +![structure](./res/VisitorObject.png) + +* 使用访问者模式必须创建具体访问者对象,遍历整个数据结构,使用访问者访问每个元素。 +* 当元素被访问到时,调用访问者的对应方法。 + +## 模式效果 + +1. 访问者模式很容易添加新操作 + + 通过添加一个新的访问者,能够对结构中所有对象定义新的操作。 +2. 访问者将相关的操作聚集,分隔不相关的 + + 相关的操作被定义在同一个访问者中,不相关的操作由不同访问者持有。 +3. 添加新的Element实例困难 + + 正如之前章节提到的,访问者要有对所有Element都有相应方法,所以添加新的Element会比较困难。 +4. 访问整个类层级结构 + + 可以使用迭代器遍历对象,但迭代器不能遍历不同类型的元素。这就要求这些元素都有相同的基类。 + + 但访问者并没有这样的限制,调用访问者的对象完全可以是有着不同的基类。 +5. 累积状态 + + 当访问者逐个访问元素时,可以累积状态,否则就要将这一状态在遍历过程传递,或者记录为全局对象。 +6. 打破了封装 + + 访问者直接访问了ConcreteElement,打破了元素的封装。 + +## 实现 + +实现时要考虑以下两个问题: + +1. 双重分发 + + 访问者模式能够给类添加方法而不修改类,这是使用了双重分发技术实现的。 + + 支持单分发的语言,决定调用什么方法的,是请求名和接受者的类型(想象多态)。 + + 双重分发意味着方法的执行由请求类型和两个接受者,例如Accept方法就有Visitor和Element共通决定。 + + +2. 由谁负责遍历对象结构? + + 可以有三个地方来实现遍历,分别是对象结构内部、访问者内部、或是另外实现迭代器。 + + 对象结构内部实现遍历是最常见的做法,因为迭代内部的元素实现起来最便捷。 + + 使用内部迭代器还是外部迭代器都可以,很大程度上取决于语言的特性。 + + 在访问者中实现遍历也是可行的,一般用来实现比较复杂的遍历逻辑,但这样的话每个具体访问者都要实现遍历的代码,会比较麻烦。 \ No newline at end of file diff --git a/BehavioralPatterns/Visitor/res/VisitorObject.png b/BehavioralPatterns/Visitor/res/VisitorObject.png new file mode 100644 index 0000000000000000000000000000000000000000..8890b6b3c8bd02c7deb24f7f5fad1a16034f68bc GIT binary patch literal 10960 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 Date: Thu, 10 May 2018 10:30:13 +0800 Subject: [PATCH 25/25] revision --- BehavioralPatterns/ChainOfReponsibility/chain.py | 7 ++++++- BehavioralPatterns/Command/README.md | 2 +- BehavioralPatterns/Interpreter/README.md | 2 +- BehavioralPatterns/Iterator/README.md | 4 ++-- BehavioralPatterns/Mediator/mediator.py | 2 ++ BehavioralPatterns/Memento/README.md | 4 ++-- CreationalPatterns/AbstractFactory/README.md | 2 +- CreationalPatterns/Builder/README.md | 4 +++- CreationalPatterns/Prototype/README.md | 2 +- StructuralPatterns/Adapter/README.md | 4 ++-- StructuralPatterns/Bridge/README.md | 6 +++--- StructuralPatterns/Composite/README.md | 2 +- StructuralPatterns/Decorator/README.md | 5 +++-- StructuralPatterns/Flyweight/README.md | 2 +- 14 files changed, 29 insertions(+), 19 deletions(-) diff --git a/BehavioralPatterns/ChainOfReponsibility/chain.py b/BehavioralPatterns/ChainOfReponsibility/chain.py index 6698f8f9e..d9b9e2806 100644 --- a/BehavioralPatterns/ChainOfReponsibility/chain.py +++ b/BehavioralPatterns/ChainOfReponsibility/chain.py @@ -6,10 +6,12 @@ class Handler: def __init__(self,successor): self._successor = successor; + def handle(self,request): i = self._handle(request) - if not i: + if not i: self._successor.handle(request) + def _handle(self, request): raise NotImplementedError('Must provide implementation in subclass.') @@ -34,6 +36,7 @@ def _handle(self, request): if 20 < request <= 30: print('request {} handled in handler 3'.format(request)) return True + class DefaultHandler(Handler): def _handle(self, request): @@ -42,8 +45,10 @@ def _handle(self, request): class Client: + def __init__(self): self.handler = ConcreteHandler1(ConcreteHandler3(ConcreteHandler2(DefaultHandler(None)))) + def delegate(self, requests): for request in requests: self.handler.handle(request) diff --git a/BehavioralPatterns/Command/README.md b/BehavioralPatterns/Command/README.md index 900253bc0..c7215fada 100644 --- a/BehavioralPatterns/Command/README.md +++ b/BehavioralPatterns/Command/README.md @@ -24,7 +24,7 @@ 1. 命令模式将对象调用执行和如何执行解耦。 2. 命令是一级对象,这意味着能够像其他对象一样操作、扩展。 -3. 可以讲多个命令集成为一个复合命令。 +3. 可以将多个命令集成为一个复合命令。 4. 很容易添加新的命令,因为这不会影响已有的类。 ## 实现 diff --git a/BehavioralPatterns/Interpreter/README.md b/BehavioralPatterns/Interpreter/README.md index e4276efec..e8c41bb3b 100644 --- a/BehavioralPatterns/Interpreter/README.md +++ b/BehavioralPatterns/Interpreter/README.md @@ -18,7 +18,7 @@ ![structure](./res/Interpreter.png) -解释器的核心,就是建立这样一个语法树,用户直接面向抽线基类,调用解释方法翻译内容。 +解释器的核心,就是建立这样一个语法树,用户直接面向抽象基类,调用解释方法翻译内容。 ## 模式效果 diff --git a/BehavioralPatterns/Iterator/README.md b/BehavioralPatterns/Iterator/README.md index 2aead4f57..d92daf790 100644 --- a/BehavioralPatterns/Iterator/README.md +++ b/BehavioralPatterns/Iterator/README.md @@ -2,7 +2,7 @@ ## 意图 提供一种顺序访问对象集合的方法,而不用关心其底层实现。 -也成为游标(Cursor)。 +也称为游标(Cursor)。 ## 适用性 @@ -71,4 +71,4 @@ 8. 空迭代器 空迭代器是一个退化的迭代器,用来判断边界条件时很有用。通过定义,空迭代器总是遍历的完成,调用IsDone的结果总是true。 -9. + diff --git a/BehavioralPatterns/Mediator/mediator.py b/BehavioralPatterns/Mediator/mediator.py index 82a2886fa..1c6e55e65 100644 --- a/BehavioralPatterns/Mediator/mediator.py +++ b/BehavioralPatterns/Mediator/mediator.py @@ -8,6 +8,7 @@ class TC: + '''Access db and report the result bt TM''' def __init__(self): self._tm = None @@ -78,6 +79,7 @@ def setTM(self, tm): class TestManager: + '''The Mediator object''' def __init__(self): self._reporter = None diff --git a/BehavioralPatterns/Memento/README.md b/BehavioralPatterns/Memento/README.md index 8928f9689..8c4672318 100644 --- a/BehavioralPatterns/Memento/README.md +++ b/BehavioralPatterns/Memento/README.md @@ -14,7 +14,7 @@ ![structure](./res/Memento.png) -Memento对于Caretaker只开放**窄接口**——Caretaker只存储和传递Memento,但不能访问其中的state(如何实现?private方法+设置Originator为友元?),对于Originator开放**宽接口**——能够访问state。 +Memento对于Caretaker只开放**窄接口**——Caretaker只存储和传递Memento,但不能访问其中的state,对于Originator开放**宽接口**——能够访问state。 ## 模式效果 @@ -39,7 +39,7 @@ Memento对于Caretaker只开放**窄接口**——Caretaker只存储和传递Mem 1. 语言的支持 - 备忘录模式需要宽窄两种接口,理想情况下实现语言要支持两层的静态保护。C++中,你可以将*宽接口设为私有*,然后将发起人设为友元,将窄接口设为公开。 + 备忘录模式需要宽窄两种接口,理想情况下实现语言要支持两层的静态保护。C++中,你可以将*宽接口设为私有,然后将发起人设为友元,将窄接口设为公开*。 2. 存储变化增量 当备忘录按照一个可预测的顺序创建和传回时,可以只存储发起人内部状态的增量信息 \ No newline at end of file diff --git a/CreationalPatterns/AbstractFactory/README.md b/CreationalPatterns/AbstractFactory/README.md index 4b96a7764..925fcb589 100644 --- a/CreationalPatterns/AbstractFactory/README.md +++ b/CreationalPatterns/AbstractFactory/README.md @@ -21,7 +21,7 @@ ![structure](./res/AbstractFactoryBasicStructure.png) ## 运作流程 -* 通畅,具体工厂在运行时创建,每个具体工厂中有产品创建的具体实现,为了创建不同的产品对象,需要使用不同的具体工厂; +* 通常,具体工厂在运行时创建,每个具体工厂中有产品创建的具体实现,为了创建不同的产品对象,需要使用不同的具体工厂; * 抽象工厂将产品的创建交给其具体工厂处理; ## 模式效果 diff --git a/CreationalPatterns/Builder/README.md b/CreationalPatterns/Builder/README.md index a3dfb4b68..f010e6702 100644 --- a/CreationalPatterns/Builder/README.md +++ b/CreationalPatterns/Builder/README.md @@ -4,7 +4,7 @@ 它可以将复杂对象的构造过程与其表现分离、抽象出来,使这个抽象过程可以构造出不同表现(属性)的对象。 ## 模式比喻 -我要一座房子住,可是我不知道怎么盖(简单的砌墙,层次较低),也不知道怎么样设计(建几个房间,几个门好看,层次较高),于是我需要找一帮**民工,他们会砌墙**,还得找个**设计师,他知道怎么设计**,我还要**确保民工听设计师的领导**,而设计师本身也不干活,光是下命令,这里砌一堵墙,这里砌一扇门,这样民工开始建设,最后,我可以向民工要房子了。在这个过程中,**设计师是什么也没有,除了他在脑子里的设计和命令,所以要房子也是跟民工要** +我要一座房子住,可是我不知道怎么盖(简单的砌墙,层次较低),也不知道怎么样设计(建几个房间,几个门好看,层次较高),于是我需要找**施工队,他们会砌墙**,还得找个**设计师,他知道怎么设计**,我还要**确保施工队听设计师的领导**,而设计师本身也不干活,光是下命令,这里砌一堵墙,这里砌一扇门,这样施工队就可以开始建设。最后,我向施工队要房子。在这个过程中,**设计师是什么也没有,除了他在脑子里的设计和命令,所以要房子最终要跟施工队要** ## 适用性 在以下场合使用生成器模式: @@ -12,6 +12,8 @@ * 创建复杂对象的算法要与对象组织的部分分离; * 对象的创建过程允许不同的表现方式 +Java/C++中的protobuf自动生成、用于构建protobuf对象的代码,应该算是生成器模式的一个实际应用。 + ## 结构 ![structure](./res/Builder.png) diff --git a/CreationalPatterns/Prototype/README.md b/CreationalPatterns/Prototype/README.md index ac598bad3..ce27bfca2 100644 --- a/CreationalPatterns/Prototype/README.md +++ b/CreationalPatterns/Prototype/README.md @@ -60,7 +60,7 @@ 原型模式最困难的就是实现Clone方法,尤其是存在环形引用时。很多语言都支持拷贝操作,但该如何解决“浅拷贝还是深拷贝”的问题? - 浅拷贝更加简单和高效,Smalltalk默认为前拷贝,C++的拷贝由成员类型决定,指针是共享一块内存的。而Clone方法大部分情况下需要深拷贝。实现时要根据具体的情况,决定哪些对象是可以共享,哪些是必须独立的。 + 浅拷贝更加简单和高效,Smalltalk默认为浅拷贝,C++的拷贝由成员类型决定,指针是共享一块内存的。而Clone方法大部分情况下需要深拷贝。实现时要根据具体的情况,决定哪些对象是可以共享,哪些是必须独立的。 如果系统中的对象提供存储和加载操作,你能够使用Clone方法非常容易地实现:存储时就是Clone到内存,加载就是从内存中Clone得到对象。 diff --git a/StructuralPatterns/Adapter/README.md b/StructuralPatterns/Adapter/README.md index 159899a20..83412d63e 100644 --- a/StructuralPatterns/Adapter/README.md +++ b/StructuralPatterns/Adapter/README.md @@ -23,13 +23,13 @@ 1. 继承 - 适配器继承操作对象和适配目标。这类适配器成为***类适配器***(***Class Adapter***)。 + 适配器继承操作对象和适配目标。这类适配器成为**类适配器**(**Class Adapter**)。 ![structure](./res/AdapterInherit.png) 2. 组合 - 适配器继承操作对象,并持有适配目标的引用。这类适配器成为***对象适配器***(***object adapter***). + 适配器继承操作对象,并持有适配目标的引用。这类适配器成为**对象适配器**(**object adapter**). ![structure](./res/AdapterComposite.png) diff --git a/StructuralPatterns/Bridge/README.md b/StructuralPatterns/Bridge/README.md index 343ec3f69..de5b9392a 100644 --- a/StructuralPatterns/Bridge/README.md +++ b/StructuralPatterns/Bridge/README.md @@ -5,8 +5,8 @@ ## 适用性 * 避免抽象与实现之间固定的绑定(例如子类实现接口方式),这样做能够实现动态切换实现。 -* 抽线和实现都会被继承。桥连模式使你能够组合不同的抽象和实现。 -* 抽象的实现的修改,不需要用户重新编译才能起作用。 +* 抽象和实现都会被继承。桥连模式使你能够组合不同的抽象和实现。 +* 修改抽象的实现时,不需要用户重新编译才能起作用。 * C++中希望对客户完全隐藏抽象的实现,可以考虑使用桥连模式,因为在C++中类的表现在类接口中是可见的。 * 系统中的类可能存在如下结构图所示的增殖情况,希望能摆脱这种糟糕的设计 @@ -14,7 +14,7 @@ >最顶层的抽象为Window,在不同的桌面平台有不同的子类XWindow和PMWindow。除了从平台角度划分,还可以从功能角度划分,存在基类IconWindow,而IconWindow也存在不同平台的实现XIconWindow和PMIconWindow。没种功能的Window都会存在多平台的实现,如果支持的平台增加了,没种功能Window也需要扩展对应实现。这就是所谓的类的增殖。 -* 希望能在多个对象间共享实现,而且这个希望是能对客户隐藏的。 +* 希望能在多个对象间共享实现,而且这个希望是对客户隐藏的。 ## 结构 diff --git a/StructuralPatterns/Composite/README.md b/StructuralPatterns/Composite/README.md index 6d0108c15..fe30a3345 100644 --- a/StructuralPatterns/Composite/README.md +++ b/StructuralPatterns/Composite/README.md @@ -86,7 +86,7 @@ 8. 生命周期管理 - 子对象的生命周期尤其父对象管理,即由Composite负责删除其中的Leaf或子Composite。 + 子对象的生命周期由其父对象管理,即由Composite负责删除其中的Leaf或子Composite。 但是,当Leaf对象是不可变且共享的,就不符合这一原则。 diff --git a/StructuralPatterns/Decorator/README.md b/StructuralPatterns/Decorator/README.md index a35aa310f..5c6bd2530 100644 --- a/StructuralPatterns/Decorator/README.md +++ b/StructuralPatterns/Decorator/README.md @@ -18,7 +18,7 @@ ![structure](./res/DecoratorStructure.png) ## 模式效果 -装饰器模式至少有两个有点、两点不足: +装饰器模式至少有两个优点、两点不足: 1. 相比与静态的继承更为灵活 @@ -34,6 +34,7 @@ 3. 装饰器和对象本身并不一致 装饰器和对象的外特性一致,但本质上并非同一事物,当需要用到对象的ID时会发生错误。 + 具体到python的装饰器中,这个问题可以被语法糖`@wraps(fn)`解决。 4. 大量的小对象 @@ -54,7 +55,7 @@ 4. “治标” vs “治本” - 装饰器是在原有行为上添加一层,可以认为是一种“治标”,另一种选择是改变对象的内部机制,称为“治标”,例如使用策略模式。此处的“治标”与“治本”并无绝对的优劣之分,不同场景下有不同的擅场。 + 装饰器是在原有行为上添加一层,可以认为是一种“治标”,另一种选择是改变对象的内部机制,称为“治本”,例如使用策略模式。此处的“治标”与“治本”并无绝对的优劣之分,不同场景下有不同的擅场。 当Component是一个重量级对象,策略模式是一个更好的选择。Component将其某个行为交给独立的策略对象,策略模式能够在不同的策略对象间切换行为。关于策略模式,在相关章节中再做展开。 diff --git a/StructuralPatterns/Flyweight/README.md b/StructuralPatterns/Flyweight/README.md index f171088cc..971945bad 100644 --- a/StructuralPatterns/Flyweight/README.md +++ b/StructuralPatterns/Flyweight/README.md @@ -61,7 +61,7 @@ 2. 管理共享对象 * client不允许直接实例化共享对象,而应委托给FlyweightFactory; * FlyweightFactory返回共享对象,或实例化对象; - * 可以使用引用计数维护共享对象,但在flyweight数量固定会较少时,没有这么做的必要 + * 可以使用引用计数维护共享对象,但在flyweight数量固定且较少时,没有这么做的必要