本文为博客转载:https://www.cnblogs.com/Liqiongyu/p/5916710.html
15. Chain of Responsibility(责任链)
本文源码寄方于github:https://github.com/w392807287/Design_pattern_of_python
参考文献:
《大话设计模式》——吴强
《Python设计模式》——pythontip.com
《23种设计模式》——http://www.cnblogs.com/beijiguangyong/
设计模式是什么?
设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样能够直接作用于我们的代码。反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。设计模式不会绑定具体的编程语言。一个好的设计模式应该能够用大部分编程语言实现(如果做不到全部的话,具体取决于语言特性)。最为重要的是,设计模式也是一把双刃剑,如果设计模式被用在不恰当的情形下将会造成灾难,进而带来无穷的麻烦。然而如果设计模式在正确的时间被用在正确地地方,它将是你的救星。
起初,你会认为“模式”就是为了解决一类特定问题而特别想出来的明智之举。说的没错,看起来的确是通过很多人一起工作,从不同的角度看待问题进而形成的一个最通用、最灵活的解决方案。也许这些问题你曾经见过或是曾经解决过,但是你的解决方案很可能没有模式这么完备。
虽然被称为“设计模式”,但是它们同“设计“领域并非紧密联系。设计模式同传统意义上的分析、设计与实现不同,事实上设计模式将一个完整的理念根植于程序中,所以它可能出现在分析阶段或是更高层的设计阶段。很有趣的是因为设计模式的具体体现是程序代码,因此可能会让你认为它不会在具体实现阶段之前出现(事实上在进入具体实现阶段之前你都没有意识到正在使用具体的设计模式)。
可以通过程序设计的基本概念来理解模式:增加一个抽象层。抽象一个事物就是隔离任何具体细节,这么做的目的是为了将那些不变的核心部分从其他细节中分离出来。当你发现你程序中的某些部分经常因为某些原因改动,而你不想让这些改动的部分引发其他部分的改动,这时候你就需要思考那些不会变动的设计方法了。这么做不仅会使代码可维护性更高,而且会让代码更易于理解,从而降低开发成本。
这里列举了三种最基本的设计模式:
- 创建模式,提供实例化的方法,为适合的状况提供相应的对象创建方法。
- 结构化模式,通常用来处理实体之间的关系,使得这些实体能够更好地协同工作。
- 行为模式,用于在不同的实体建进行通信,为实体之间的通信提供更容易,更灵活的通信方法。
创建型
1. Factory Method(工厂方法)
2. Abstract Factory(抽象工厂)
3. Builder(建造者)
4. Prototype(原型)
5. Singleton(单例)
结构型
6. Adapter Class/Object(适配器)
7. Bridge(桥接)
8. Composite(组合)
9. Decorator(装饰)
10. Facade(外观)
11. Flyweight(享元)
12. Proxy(代理)
行为型
13. Interpreter(解释器)
14. Template Method(模板方法)
15. Chain of Responsibility(责任链)
16. Command(命令)
17. Iterator(迭代器)
18. Mediator(中介者)
19. Memento(备忘录)
20. Observer(观察者)
21. State(状态)
22. Strategy(策略)
23. Visitor(访问者)
创建型
1.Factory Method(工厂方法)
意图:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
适用性:
当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类来指定它所创建的对象的时候。
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
实现:
-
#!/usr/bin/python
-
#coding:utf8
-
'''
-
Factory Method
-
'''
-
-
class
ChinaGetter:
-
"""A simple localizer a la gettext"""
-
def
__init__(
self):
-
self.trans =
dict(dog=
u"小狗", cat=
u"小猫")
-
-
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, China=ChinaGetter)
-
return languages[language]()
-
-
# Create our localizers
-
e, g = get_localizer(
"English"), get_localizer(
"China")
-
# Localize some text
-
for msgid
in
"dog parrot cat bear".split():
-
print(e.get(msgid), g.get(msgid))
2. Abstract Factory(抽象工厂)
意图:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用性:
一个系统要独立于它的产品的创建、组合和表示时。
一个系统要由多个产品系列中的一个来配置时。
当你要强调一系列相关的产品对象的设计以便进行联合使用时。
当你提供一个产品类库,而只想显示它们的接口而不是实现时。
实现:
-
#!/usr/bin/python
-
#coding:utf8
-
'''
-
Abstract Factory
-
'''
-
-
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(
"This is a lovely",
str(pet))
-
print(
"It says", pet.speak())
-
print(
"It eats", 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__":
-
shop = PetShop()
-
for i
in
range(
3):
-
shop.pet_factory = get_factory()
-
shop.show_pet()
-
print(
"=" *
20)
3. Builder(建造者)
意图:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性:
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
当构造过程必须允许被构造的对象有不同的表示时。
实现:
-
#!/usr/bin/python
-
#coding:utf8
-
-
"""
-
Builder
-
"""
-
-
# 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: %s | Size: %s' % (self.floor, self.size)
-
-
-
# 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)
4. Prototype(原型)
意图:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性:
当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者为了避免创建一个与产品类层次平行的工厂类层次时;或者当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
实现:
-
#!/usr/bin/python
-
#coding:utf8
-
'''
-
Prototype
-
'''
-
-
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
-
-
-
def
main():
-
class
A:
-
def
__str__(
self):
-
return
"I am A"
-
-
a = A()
-
prototype = Prototype()
-
prototype.register_object(
'a', a)
-
b = prototype.clone(
'a', a=
1, b=
2, c=
3)
-
-
print(a)
-
print(b.a, b.b, b.c)
-
-
-
if __name__ ==
'__main__':
-
main()
5. Singleton(单例)
意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性:
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
实现:
-
#!/usr/bin/python
-
#coding:utf8
-
'''
-
Singleton
-
'''
-
-
class
Singleton(
object):
-
''''' A python style singleton '''
-
-
def
__new__(
cls, *args, **kw):
-
if
not
hasattr(cls,
'_instance'):
-
org =
super(Singleton, cls)
-
cls._instance = org.__new__(cls, *args, **kw)
-
return cls._instance
-
-
-
if __name__ ==
'__main__':
-
class
SingleSpam(
Singleton):
-
def
__init__(
self, s):
-
self.s = s
-
-
def
__str__(
self):
-
return self.s
-
-
-
s1 = SingleSpam(
'spam')
-
print
id(s1), s1
-
s2 = SingleSpam(
'spa')
-
print
id(s2), s2
-
print
id(s1), s1
结构型
6. Adapter Class/Object(适配器)
意图:
将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适用性:
你想使用一个已经存在的类,而它的接口不符合你的需求。
你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
(仅适用于对象Adapter )你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Adapter
-
-
'''
-
-
-
-
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%s" % (
"!" * octane_level)
-
-
-
-
-
-
class
Adapter(
object):
-
-
"""
-
-
Adapts an object by replacing methods.
-
-
Usage:
-
-
dog = Dog
-
-
dog = Adapter(dog, dict(make_noise=dog.bark))
-
-
"""
-
-
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()
-
-
car_noise =
lambda: car.make_noise(
3)
-
-
objects.append(Adapter(car,
dict(make_noise=car_noise)))
-
-
-
-
for obj
in objects:
-
-
print
"A", obj.name,
"goes", obj.make_noise()
-
-
-
-
-
-
if __name__ ==
"__main__":
-
-
main()
7. Bridge(桥接)
意图:
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
适用性:
你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
(C++)你想对客户完全隐藏抽象的实现部分。在C++中,类的表示在类接口中是可见的。
有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。Rumbaugh 称这种类层次结构为“嵌套的普化”(nested generalizations )。
你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是Coplien 的String 类[ Cop92 ],在这个类中多个对象可以共享同一个字符串表示(StringRep)。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Bridge
-
-
'''
-
-
-
-
-
-
# 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()
8. Composite(组合)
意图:
将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。
适用性:
你想表示对象的部分-整体层次结构。
你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
-
-
"""
-
-
Composite
-
-
"""
-
-
-
-
class
Component:
-
-
def
__init__(
self,strName):
-
-
self.m_strName = strName
-
-
def
Add(
self,com):
-
-
pass
-
-
def
Display(
self,nDepth):
-
-
pass
-
-
-
-
class
Leaf(
Component):
-
-
def
Add(
self,com):
-
-
print
"leaf can't add"
-
-
def
Display(
self,nDepth):
-
-
strtemp =
"-" * nDepth
-
-
strtemp=strtemp+self.m_strName
-
-
print strtemp
-
-
-
-
class
Composite(
Component):
-
-
def
__init__(
self,strName):
-
-
self.m_strName = strName
-
-
self.c = []
-
-
def
Add(
self,com):
-
-
self.c.append(com)
-
-
def
Display(
self,nDepth):
-
-
strtemp =
"-"*nDepth
-
-
strtemp=strtemp+self.m_strName
-
-
print strtemp
-
-
for com
in self.c:
-
-
com.Display(nDepth+
2)
-
-
-
-
if __name__ ==
"__main__":
-
-
p = Composite(
"Wong")
-
-
p.Add(Leaf(
"Lee"))
-
-
p.Add(Leaf(
"Zhao"))
-
-
p1 = Composite(
"Wu")
-
-
p1.Add(Leaf(
"San"))
-
-
p.Add(p1)
-
-
p.Display(
1);
9. Decorator(装饰)
意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
适用性:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
处理那些可以撤消的职责。
当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Decorator
-
-
'''
-
-
-
-
class
foo(
object):
-
-
def
f1(
self):
-
-
print(
"original f1")
-
-
-
-
def
f2(
self):
-
-
print(
"original f2")
-
-
-
-
-
-
class
foo_decorator(
object):
-
-
def
__init__(
self, decoratee):
-
-
self._decoratee = decoratee
-
-
-
-
def
f1(
self):
-
-
print(
"decorated f1")
-
-
self._decoratee.f1()
-
-
-
-
def
__getattr__(
self, name):
-
-
return
getattr(self._decoratee, name)
-
-
-
-
u = foo()
-
-
v = foo_decorator(u)
-
-
v.f1()
-
-
v.f2()
10. Facade(外观)
意图:
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
适用性:
当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过facade层。
客户程序与抽象类的实现部分之间存在着很大的依赖性。引入facade 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
当你需要构建一个层次结构的子系统时,使用facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们之间的依赖关系。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Decorator
-
-
'''
-
-
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()
11. Flyweight(享元)
意图:
运用共享技术有效地支持大量细粒度的对象。
适用性:
一个应用程序使用了大量的对象。
完全由于使用大量的对象,造成很大的存储开销。
对象的大多数状态都可变为外部状态。
如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
应用程序不依赖于对象标识。由于Flyweight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Flyweight
-
-
'''
-
-
-
-
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
"<Card: %s%s>" % (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))
12. Proxy(代理)
意图:
为其他对象提供一种代理以控制对这个对象的访问。
适用性:
在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。下面是一 些可以使用Proxy 模式常见情况:
1) 远程代理(Remote Proxy )为一个对象在不同的地址空间提供局部代表。 NEXTSTEP[Add94] 使用NXProxy 类实现了这一目的。Coplien[Cop92] 称这种代理为“大使” (Ambassador )。
2 )虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的ImageProxy 就是这样一种代理的例子。
3) 保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。例如,在Choices 操作系统[ CIRM93]中KemelProxies为操作系统对象提供 了访问保护。
4 )智能指引(Smart Reference )取代了简单的指针,它在访问对象时执行一些附加操作。 它的典型用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为SmartPointers[Ede92 ] )。
当第一次引用一个持久对象时,将它装入内存。
在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Proxy
-
-
'''
-
-
-
-
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()
行为型
13. Interpreter(解释器)
意图:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用性:
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好:
该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Interpreter
-
-
'''
-
-
-
-
class
Context:
-
-
def
__init__(
self):
-
-
self.
input=
""
-
-
self.output=
""
-
-
-
-
class
AbstractExpression:
-
-
def
Interpret(
self,context):
-
-
pass
-
-
-
-
class
Expression(
AbstractExpression):
-
-
def
Interpret(
self,context):
-
-
print
"terminal interpret"
-
-
-
-
class
NonterminalExpression(
AbstractExpression):
-
-
def
Interpret(
self,context):
-
-
print
"Nonterminal interpret"
-
-
-
-
if __name__ ==
"__main__":
-
-
context=
""
-
-
c = []
-
-
c = c + [Expression()]
-
-
c = c + [NonterminalExpression()]
-
-
c = c + [Expression()]
-
-
c = c + [Expression()]
-
-
for a
in c:
-
-
a.Interpret(context)
14. Template Method(模板方法)
意图:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
适用性:
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke 和Johnson所描述过的“重分解以一般化”的一个很好的例子[ OJ93 ]。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
控制子类扩展。模板方法只在特定点调用“hook ”操作(参见效果一节),这样就只允许在这些点进行扩展。
实现:
-
#!/usr/bin/python
-
-
#coding:utf8
-
-
'''
-
-
Template Method
-
-
'''
-
-
-
-
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
i