作者:五岳
上一周把《大话设计模式》看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多、偶尔会用到一些脚本语言写脚本的人来说,很是开阔眼界。《大话设计模式》的代码使用C#写成的,而在本人接触到的面向对象语言中,只对C++和Python还算了解,为了加深对各个模式的理解,我在网上下载了一个C++版的源代码,并根据自己的理解边读这本书边动手实践C++源代码,同时将其改写成了Python代码,算是一箭三雕吧。
由于这些代码的目的是展示各个设计模式而非完成一个具体的复杂任务,基于C++版本改写,例子的取材也和《大话设计模式》基本相同,再加上个人水平有限,因此这些Python版代码写的比较简单,虽然能跑起来是不假,不过难免有bug,而且实现也不一定最优,C++的味道比较浓而不够pythonic,还请高手包容指正。不过我还是尽量把或多或少有些pythonic的东西放在每个模式的“代码特点”部分进行展示,而这个“代码特点”里也不仅仅是pythonic的东西。
使用Python版本为2.6。
配图同样摘自《大话设计模式》,因此是C#风格的UML类图,为了便于排版已经缩小了。
一、简单工厂模式
模式特点:工厂根据条件产生不同功能的类。
程序实例:四则运算计算器,根据用户的输入产生相应的运算类,用这个运算类处理具体的运算。
代码特点:C/C++中的switch...case...分支使用字典的方式代替。
使用异常机制对除数为0的情况进行处理。
1 class Operation:
2 def GetResult(self):
3 pass
4
5 class OperationAdd(Operation):
6 def GetResult(self):
7 return self.op1+self.op2
8
9
10 class OperationSub(Operation):
11 def GetResult(self):
12 return self.op1-self.op2
13
14
15 class OperationMul(Operation):
16 def GetResult(self):
17 return self.op1*self.op2
18
19
20 class OperationDiv(Operation):
21 def GetResult(self):
22 try:
23 result = self.op1/self.op2
24 return result
25 except:
26 print "error:divided by zero."
27 return 0
28
29 class OperationUndef(Operation):
30 def GetResult(self):
31 print "Undefine operation."
32 return 0
33
34 class OperationFactory:
35 operation = {}
36 operation["+"] = OperationAdd();
37 operation["-"] = OperationSub();
38 operation["*"] = OperationMul();
39 operation["/"] = OperationDiv();
40 def createOperation(self,ch):
41 if ch in self.operation:
42 op = self.operation[ch]
43 else:
44 op = OperationUndef()
45 return op
46
47 if __name__ == "__main__":
48 op = raw_input("operator: ")
49 opa = input("a: ")
50 opb = input("b: ")
51 factory = OperationFactory()
52 cal = factory.createOperation(op)
53 cal.op1 = opa
54 cal.op2 = opb
55 print cal.GetResult()
View Code
二、策略模式
模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端。
程序实例:商场收银软件,需要根据不同的销售策略方式进行收费
代码特点:不同于同例1,这里使用字典是为了避免关键字不在字典导致bug的陷阱。
1 class CashSuper:
2 def AcceptCash(self,money):
3 return 0
4
5 class CashNormal(CashSuper):
6 def AcceptCash(self,money):
7 return money
8
9 class CashRebate(CashSuper):
10 discount = 0
11 def __init__(self,ds):
12 self.discount = ds
13 def AcceptCash(self,money):
14 return money * self.discount
15
16 class CashReturn(CashSuper):
17 total = 0;
18 ret = 0;
19 def __init__(self,t,r):
20 self.total = t
21 self.ret = r
22 def AcceptCash(self,money):
23 if (money>=self.total):
24 return money - self.ret
25 else:
26 return money
27
28 class CashContext:
29 def __init__(self,csuper):
30 self.cs = csuper
31 def GetResult(self,money):
32 return self.cs.AcceptCash(money)
33
34 if __name__ == "__main__":
35 money = input("money:")
36 strategy = {}
37 strategy[1] = CashContext(CashNormal())
38 strategy[2] = CashContext(CashRebate(0.8))
39 strategy[3] = CashContext(CashReturn(300,100))
40 ctype = input("type:[1]for normal,[2]for 80% discount [3]for 300 -100.")
41 if ctype in strategy:
42 cc = strategy[ctype]
43 else:
44 print "Undefine type.Use normal mode."
45 cc = strategy[1]
46 print "you will pay:%d" %(cc.GetResult(money))
View Code
三、装饰模式
模式特点:动态地为对象增加额外的职责
程序实例:展示一个人一件一件穿衣服的过程。
代码特点:无
1 class Person:
2 def __init__(self,tname):
3 self.name = tname
4 def Show(self):
5 print "dressed %s" %(self.name)
6
7 class Finery(Person):
8 componet = None
9 def __init__(self):
10 pass
11 def Decorate(self,ct):
12 self.componet = ct
13 def Show(self):
14 if(self.componet!=None):
15 self.componet.Show()
16
17 class TShirts(Finery):
18 def __init__(self):
19 pass
20 def Show(self):
21 print "Big T-shirt "
22 self.componet.Show()
23
24 class BigTrouser(Finery):
25 def __init__(self):
26 pass
27 def Show(self):
28 print "Big Trouser "
29 self.componet.Show()
30
31 if __name__ == "__main__":
32 p = Person("somebody")
33 bt = BigTrouser()
34 ts = TShirts()
35 bt.Decorate(p)
36 ts.Decorate(bt)
37 ts.Show()
View Code
四、代理模式
模式特点:为其他对象提供一种代理以控制对这个对象的访问。
程序实例:同模式特点描述。
代码特点:无
1 class Interface :
2 def Request(self):
3 return 0
4
5 class RealSubject(Interface):
6 def Request(self):
7 print "Real request."
8
9 class Proxy(Interface):
10 def Request(self):
11 self.real = RealSubject()
12 self.real.Request()
13
14 if __name__ == "__main__":
15 p = Proxy()
16 p.Request()
View Code
五、工厂方法模式
模式特点:定义一个用于创建对象的接口,让子类决定实例化哪一个类。这使得一个类的实例化延迟到其子类。
程序实例:基类雷锋类,派生出学生类和志愿者类,由这两种子类完成“学雷锋”工作。子类的创建由雷锋工厂的对应的子类完成。
代码特点:无
1 class LeiFeng:
2 def Sweep(self):
3 print "LeiFeng sweep"
4
5 class Student(LeiFeng):
6 def Sweep(self):
7 print "Student sweep"
8
9 class Volenter(LeiFeng):
10 def Sweep(self):
11 print "Volenter sweep"
12
13 class LeiFengFactory:
14 def CreateLeiFeng(self):
15 temp = LeiFeng()
16 return temp
17
18 class StudentFactory(LeiFengFactory):
19 def CreateLeiFeng(self):
20 temp = Student()
21 return temp
22
23 class VolenterFactory(LeiFengFactory):
24 def CreateLeiFeng(self):
25 temp = Volenter()
26 return temp
27
28 if __name__ == "__main__":
29 sf = StudentFactory()
30 s=sf.CreateLeiFeng()
31 s.Sweep()
32 sdf = VolenterFactory()
33 sd=sdf.CreateLeiFeng()
34 sd.Sweep()
View Code
六、原型模式
模式特点:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
程序实例:从简历原型,生成新的简历
代码特点:简历类Resume提供的Clone()方法其实并不是真正的Clone,只是为已存在对象增加了一次引用。
Python为对象提供的copy模块中的copy方法和deepcopy方法已经实现了原型模式,但由于例子的层次较浅,二者看不出区别。
1 import copy
2 class WorkExp:
3 place=""
4 year=0
5
6 class Resume:
7 name = ''
8 age = 0
9 def __init__(self,n):
10 self.name = n
11 def SetAge(self,a):
12 self.age = a
13 def SetWorkExp(self,p,y):
14 self.place = p
15 self.year = y
16 def Display(self):
17 print self.age
18 print self.place
19 print self.year
20 def Clone(self):
21 #实际不是“克隆”,只是返回了自身
22 return self
23
24 if __name__ == "__main__":
25 a = Resume("a")
26 b = a.Clone()
27 c = copy.copy(a)
28 d = copy.deepcopy(a)
29 a.SetAge(7)
30 b.SetAge(12)
31 c.SetAge(15)
32 d.SetAge(18)
33 a.SetWorkExp("PrimarySchool",1996)
34 b.SetWorkExp("MidSchool",2001)
35 c.SetWorkExp("HighSchool",2004)
36 d.SetWorkExp("University",2007)
37 a.Display()
38 b.Display()
39 c.Display()
40 d.Display()
View Code
七、模板方法模式
模式特点:定义一个操作中的算法骨架,将一些步骤延迟至子类中。
程序实例:考试时使用同一种考卷(父类),不同学生上交自己填写的试卷(子类方法的实现)
代码特点:无
1 class TestPaper:
2 def TestQuestion1(self):
3 print "Test1:A. B. C. D."
4 print "(%s)" %self.Answer1()
5
6 def TestQuestion2(self):
7 print "Test1:A. B. C. D."
8 print "(%s)" %self.Answer2()
9 def Answer1(self):
10 return ""
11 def Answer2(self):
12 return ""
13
14 class TestPaperA(TestPaper):
15 def Answer1(self):
16 return "B"
17 def Answer2(self):
18 return "C";
19
20 class TestPaperB(TestPaper):
21 def Answer1(self):
22 return "D"
23 def Answer2(self):
24 return "D";
25
26 if __name__ == "__main__":
27 s1 = TestPaperA()
28 s2 = TestPaperB()
29 print "student 1"
30 s1.TestQuestion1()
31 s1.TestQuestion2()
32 print "student 2"
33 s2.TestQuestion1()
34 s2.TestQuestion2()
View Code
八、外观模式
模式特点:为一组调用提供一致的接口。
程序实例:接口将几种调用分别组合成为两组,用户通过接口调用其中的一组。
代码特点:无
1 class SubSystemOne:
2 def MethodOne(self):
3 print "SubSysOne"
4
5 class SubSystemTwo:
6 def MethodTwo(self):
7 print "SubSysTwo"
8
9 class SubSystemThree:
10 def MethodThree(self):
11 print "SubSysThree"
12
13 class SubSystemFour:
14 def MethodFour(self):
15 print "SubSysFour"
16
17
18 class Facade:
19 def __init__(self):
20 self.one = SubSystemOne()
21 self.two = SubSystemTwo()
22 self.three = SubSystemThree()
23 self.four = SubSystemFour()
24 def MethodA(self):
25 print "MethodA"
26 self.one.MethodOne()
27 self.two.MethodTwo()
28 self.four.MethodFour()
29 def MethodB(self):
30 print "MethodB"
31 self.two.MethodTwo()
32 self.three.MethodThree()
33
34 if __name__ == "__main__":
35 facade = Facade()
36 facade.MethodA()
37 facade.MethodB()
View Code
九、建造者模式
模式特点:将一个复杂对象的构建(Director)与它的表示(Builder)分离,使得同样的构建过程可以创建不同的表示(ConcreteBuilder)。
程序实例:“画”出一个四肢健全(头身手腿)的小人
代码特点:无
1 class Person:
2 def CreateHead(self):
3 pass
4 def CreateHand(self):
5 pass
6 def CreateBody(self):
7 pass
8 def CreateFoot(self):
9 pass
10
11 class ThinPerson(Person):
12 def CreateHead(self):
13 print "thin head"
14 def CreateHand(self):
15 print "thin hand"
16 def CreateBody(self):
17 print "thin body"
18 def CreateFoot(self):
19 print "thin foot"
20
21 class ThickPerson(Person):
22 def CreateHead(self):
23 print "thick head"
24 def CreateHand(self):
25 print "thick hand"
26 def CreateBody(self):
27 print "thick body"
28 def CreateFoot(self):
29 print "thick foot"
30
31 class Director:
32 def __init__(self,temp):
33 self.p = temp
34 def Create(self):
35 self.p.CreateHead()
36 self.p.CreateBody()
37 self.p.CreateHand()
38 self.p.CreateFoot()
39
40 if __name__ == "__main__":
41 p = ThickPerson()
42 d = Director(p)
43 d.Create()
View Code
十、观察者模式
模式特点:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,当主题对象状态发生变化时会通知所有观察者。
程序实例:公司里有两种上班时趁老板不在时偷懒的员工:看NBA的和看股票行情的,并且事先让老板秘书当老板出现时通知他们继续做手头上的工作。
程序特点:无
1 class Observer:
2 def __init__(self,strname,strsub):
3 self.name = strname
4 self.sub = strsub
5 def Update(self):
6 pass
7
8 class StockObserver(Observer):
9 #no need to rewrite __init__()
10 def Update(self):
11 print "%s:%s,stop watching Stock and go on work!" %(self.name,self.sub.action)
12
13 class NBAObserver(Observer):
14 def Update(self):
15 print "%s:%s,stop watching NBA and go on work!" %(self.name,self.sub.action)
16
17 class SecretaryBase:
18 def __init__(self):
19 self.observers = []
20 def Attach(self,new_observer):
21 pass
22 def Notify(self):
23 pass
24
25 class Secretary(SecretaryBase):
26 def Attach(self,new_observer):
27 self.observers.append(new_observer)
28 def Notify(self):
29 for p in self.observers:
30 p.Update()
31
32 if __name__ == "__main__":
33 p = Secretary()
34 s1 = StockObserver("xh",p)
35 s2 = NBAObserver("wyt",p)
36 p.Attach(s1);
37 p.Attach(s2);
38 p.action = "WARNING:BOSS ";
39 p.Notify()
View Code
十一、抽象工厂模式
模式特点:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类。
程序实例:提供对不同的数据库访问的支持。
IUser和IDepartment是两种不同的抽象产品,它们都有Access和SQL Server这两种不同的实现;IFactory是产生IUser和IDepartment的抽象工厂,根据具体实现(AccessFactory和SqlFactory)产生对应的具体的对象(CAccessUser与CAccessDepartment,或者CSqlUser与CSqlDepartment)。
代码特点:无
1 class IUser:
2 def GetUser(self):
3 pass
4 def InsertUser(self):
5 pass
6
7 class IDepartment:
8 def GetDepartment(self):
9 pass
10 def InsertDepartment(self):
11 pass
12
13 class CAccessUser(IUser):
14 def GetUser(self):
15 print "Access GetUser"
16 def InsertUser(self):
17 print "Access InsertUser"
18
19
20 class CAccessDepartment(IDepartment):
21 def GetDepartment(self):
22 print "Access GetDepartment"
23 def InsertDepartment(self):
24 print "Access InsertDepartment"
25
26 class CSqlUser(IUser):
27 def GetUser(self):
28 print "Sql GetUser"
29 def InsertUser(self):
30 print "Sql InsertUser"
31
32
33 class CSqlDepartment(IDepartment):
34 def GetDepartment(self):
35 print "Sql GetDepartment"
36 def InsertDepartment(self):
37 print "Sql InsertDepartment"
38
39 class IFactory:
40 def CreateUser(self):
41 pass
42 def CreateDepartment(self):
43 pass
44
45 class AccessFactory(IFactory):
46 def CreateUser(self):
47 temp=CAccessUser()
48 return temp
49 def CreateDepartment(self):
50 temp = CAccessDepartment()
51 return temp
52
53 class SqlFactory(IFactory):
54 def CreateUser(self):
55 temp = CSqlUser()
56 return temp
57 def CreateDepartment(self):
58 temp = CSqlDepartment()
59 return temp
60
61 if __name__ == "__main__":
62 factory = SqlFactory()
63 user=factory.CreateUser()
64 depart=factory.CreateDepartment()
65 user.GetUser()
66 depart.GetDepartment()
View Code
十二、状态模式
模式特点:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
程序实例:描述一个程序员的工作状态,当需要改变状态时发生改变,不同状态下的方法实现不同
代码特点:无
1 class State:
2 def WirteProgram(self):
3 pass
4
5 class Work:
6 def __init__(self):
7 self.hour = 9
8 self.current = ForenoonState()
9 def SetState(self,temp):
10 self.current = temp
11 def WriteProgram(self):
12 self.current.WriteProgram(self)
13
14 class NoonState(State):
15 def WriteProgram(self,w):
16 print "noon working"
17 if (w.hour<13):
18 print "fun."
19 else:
20 print "need to rest."
21
22 class ForenoonState(State):
23 def WriteProgram(self,w):
24 if (w.hour<12):
25 print "morning working"
26 print "energetic"
27 else:
28 w.SetState(NoonState())
29 w.WriteProgram()
30
31 if __name__ == "__main__":
32 mywork = Work()
33 mywork.hour = 9
34 mywork.WriteProgram()
35 mywork.hour =14
36 mywork.WriteProgram()
View Code
十三、适配器模式
模式特点:将一个类的接口转换成为客户希望的另外一个接口。
程序实例:用户通过适配器使用一个类的方法。
代码特点:无
1 class Target:
2 def Request():
3 print "common request."
4
5 class Adaptee(Target):
6 def SpecificRequest(self):
7 print "specific request."
8
9 class Adapter(Target):
10 def __init__(self,ada):
11 self.adaptee = ada
12 def Request(self):
13 self.adaptee.SpecificRequest()
14
15 if __name__ == "__main__":
16 adaptee = Adaptee()
17 adapter = Adapter(adaptee)
18 adapter.Request()
View Code
十四、备忘录模式
模式特点:在不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,以后可以将对象恢复到这个状态。
程序实例:将Originator对象的状态封装成Memo对象保存在Caretaker内
代码特点:无
1 class Originator:
2 def __init__(self):
3 self.state = ""
4 def Show(self):
5 print self.state
6 def CreateMemo(self):
7 return Memo(self.state)
8 def SetMemo(self,memo):
9 self.state = memo.state
10
11 class Memo:
12 state= ""
13 def __init__(self,ts):
14 self.state = ts
15
16 class Caretaker:
17 memo = ""
18
19 if __name__ == "__main__":
20 on = Originator()
21 on.state = "on"
22 on.Show()
23 c = Caretaker()
24 c.memo=on.CreateMemo()
25 on.state="off"
26 on.Show()
27 on.SetMemo(c.memo)
28 on.Show()
View Code
十五、组合模式
模式特点:将对象组合成成树形结构以表示“部分-整体”的层次结构
程序实例:公司人员的组织结构
代码特点:无
1 class Component:
2 def __init__(self,strName):
3 self.m_strName = strName
4 def Add(self,com):
5 pass
6 def Display(self,nDepth):
7 pass
8
9 class Leaf(Component):
10 def Add(self,com):
11 print "leaf can't add"
12 def Display(self,nDepth):
13 strtemp = ""
14 for i in range(nDepth):
15 strtemp=strtemp+"-"
16 strtemp=strtemp+self.m_strName
17 print strtemp
18
19 class Composite(Component):
20 def __init__(self,strName):
21 self.m_strName = strName
22 self.c = []
23 def Add(self,com):
24 self.c.append(com)
25 def Display(self,nDepth):
26 strtemp=""
27 for i in range(nDepth):
28 strtemp=strtemp+"-"
29 strtemp=strtemp+self.m_strName
30 print strtemp
31 for com in self.c:
32 com.Display(nDepth+2)
33
34 if __name__ == "__main__":
35 p = Composite("Wong")
36 p.Add(Leaf("Lee"))
37 p.Add(Leaf("Zhao"))
38 p1 = Composite("Wu")
39 p1.Add(Leaf("San"))
40 p.Add(p1)
41 p.Display(1);
View Code
十六、迭代器模式
模式特点:提供方法顺序访问一个聚合对象中各元素,而又不暴露该对象的内部表示
说明:这个模式没有写代码实现,原因是使用Python的列表和for ... in list就能够完成不同类型对象聚合的迭代功能了。
十七、单例模式
模式特点:保证类仅有一个实例,并提供一个访问它的全局访问点。
说明: 为了实现单例模式费了不少工夫,后来查到一篇博文对此有很详细的介绍,而且实现方式也很丰富,通过对代码的学习可以了解更多Python的用法。以下的代码出自GhostFromHeaven的专栏,地址:。不过正如其作者在Python单例模式终极版所说:
我要问的是,Python真的需要单例模式吗?我指像其他编程语言中的单例模式。
答案是:不需要!
因为,Python有模块(module),最pythonic的单例典范。
模块在在一个应用程序中只有一份,它本身就是单例的,将你所需要的属性和方法,直接暴露在模块中变成模块的全局变量和方法即可!
1 #-*- encoding=utf-8 -*-
2 print '----------------------方法1--------------------------'
3 #方法1,实现__new__方法
4 #并在将一个类的实例绑定到类变量_instance上,
5 #如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
6 #如果cls._instance不为None,直接返回cls._instance
7 class Singleton(object):
8 def __new__(cls, *args, **kw):
9 if not hasattr(cls, '_instance'):
10 orig = super(Singleton, cls)
11 cls._instance = orig.__new__(cls, *args, **kw)
12 return cls._instance
13
14 class MyClass(Singleton):
15 a = 1
16
17 one = MyClass()
18 two = MyClass()
19
20 two.a = 3
21 print one.a
22 #3
23 #one和two完全相同,可以用id(), ==, is检测
24 print id(one)
25 #29097904
26 print id(two)
27 #29097904
28 print one == two
29 #True
30 print one is two
31 #True
32
33 print '----------------------方法2--------------------------'
34 #方法2,共享属性;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)
35 #同一个类的所有实例天然拥有相同的行为(方法),
36 #只需要保证同一个类的所有实例具有相同的状态(属性)即可
37 #所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict)
38 #可参看:http://code.activestate.com/recipes/66531/
39 class Borg(object):
40 _state = {}
41 def __new__(cls, *args, **kw):
42 ob = super(Borg, cls).__new__(cls, *args, **kw)
43 ob.__dict__ = cls._state
44 return ob
45
46 class MyClass2(Borg):
47 a = 1
48
49 one = MyClass2()
50 two = MyClass2()
51
52 #one和two是两个不同的对象,id, ==, is对比结果可看出
53 two.a = 3
54 print one.a
55 #3
56 print id(one)
57 #28873680
58 print id(two)
59 #28873712
60 print one == two
61 #False
62 print one is two
63 #False
64 #但是one和two具有相同的(同一个__dict__属性),见:
65 print id(one.__dict__)
66 #30104000
67 print id(two.__dict__)
68 #30104000
69
70 print '----------------------方法3--------------------------'
71 #方法3:本质上是方法1的升级(或者说高级)版
72 #使用__metaclass__(元类)的高级python用法
73 class Singleton2(type):
74 def __init__(cls, name, bases, dict):
75 super(Singleton2, cls).__init__(name, bases, dict)
76 cls._instance = None
77 def __call__(cls, *args, **kw):
78 if cls._instance is None:
79 cls._instance = super(Singleton2, cls).__call__(*args, **kw)
80 return cls._instance
81
82 class MyClass3(object):
83 __metaclass__ = Singleton2
84
85 one = MyClass3()
86 two = MyClass3()
87
88 two.a = 3
89 print one.a
90 #3
91 print id(one)
92 #31495472
93 print id(two)
94 #31495472
95 print one == two
96 #True
97 print one is two
98 #True
99
100 print '----------------------方法4--------------------------'
101 #方法4:也是方法1的升级(高级)版本,
102 #使用装饰器(decorator),
103 #这是一种更pythonic,更elegant的方法,
104 #单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的
105 def singleton(cls, *args, **kw):
106 instances = {}
107 def _singleton():
108 if cls not in instances:
109 instances[cls] = cls(*args, **kw)
110 return instances[cls]
111 return _singleton
112
113 @singleton
114 class MyClass4(object):
115 a = 1
116 def __init__(self, x=0):
117 self.x = x
118
119 one = MyClass4()
120 two = MyClass4()
121
122 two.a = 3
123 print one.a
124 #3
125 print id(one)
126 #29660784
127 print id(two)
128 #29660784
129 print one == two
130 #True
131 print one is two
132 #True
133 one.x = 1
134 print one.x
135 #1
136 print two.x
137 #1
View Code
十八、桥接模式
模式特点:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
程序实例:两种品牌的手机,要求它们都可以运行游戏和通讯录两个软件,而不是为每个品牌的手机都独立编写不同的软件。
代码特点:虽然使用了object的新型类,不过在这里不是必须的,是对在Python2.2之后“尽量使用新型类”的建议的遵从示范。
1 class HandsetSoft(object):
2 def Run(self):
3 pass
4
5 class HandsetGame(HandsetSoft):
6 def Run(self):
7 print "Game"
8
9 class HandsetAddressList(HandsetSoft):
10 def Run(self):
11 print "Address List"
12
13 class HandsetBrand(object):
14 def __init__(self):
15 self.m_soft = None
16 def SetHandsetSoft(self,temp):
17 self.m_soft= temp
18 def Run(self):
19 pass
20
21 class HandsetBrandM(HandsetBrand):
22 def Run(self):
23 if not (self.m_soft == None):
24 print "BrandM"
25 self.m_soft.Run()
26
27 class HandsetBrandN(HandsetBrand):
28 def Run(self):
29 if not (self.m_soft == None):
30 print "BrandN"
31 self.m_soft.Run()
32
33 if __name__ == "__main__":
34 brand = HandsetBrandM()
35 brand.SetHandsetSoft(HandsetGame())
36 brand.Run()
37 brand.SetHandsetSoft(HandsetAddressList())
38 brand.Run()
View Code
十九、命令模式
模式特点:将请求封装成对象,从而使可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
程序实例:烧烤店有两种食物,羊肉串和鸡翅。客户向服务员点单,服务员将点好的单告诉大厨,由大厨进行烹饪。
代码特点:注意在遍历列表时不要用注释的方式删除,否则会出现bug。bug示例程序附在后面,我认为这是因为remove打乱了for迭代查询列表的顺序导致的。
1 class Barbucer:
2 def MakeMutton(self):
3 print "Mutton"
4 def MakeChickenWing(self):
5 print "Chicken Wing"
6
7 class Command:
8 def __init__(self,temp):
9 self.receiver=temp
10 def ExecuteCmd(self):
11 pass
12
13 class BakeMuttonCmd(Command):
14 def ExecuteCmd(self):
15 self.receiver.MakeMutton()
16
17 class ChickenWingCmd(Command):
18 def ExecuteCmd(self):
19 self.receiver.MakeChickenWing()
20
21 class Waiter:
22 def __init__(self):
23 self.order =[]
24 def SetCmd(self,command):
25 self.order.append(command)
26 print "Add Order"
27 def Notify(self):
28 for cmd in self.order:
29 #self.order.remove(cmd)
30 #lead to a bug
31 cmd.ExecuteCmd()
32
33
34 if __name__ == "__main__":
35 barbucer=Barbucer()
36 cmd=BakeMuttonCmd(barbucer)
37 cmd2=ChickenWingCmd(barbucer)
38 girl=Waiter()
39 girl.SetCmd(cmd)
40 girl.SetCmd(cmd2)
41 girl.Notify()
View Code
在for中remove会导致bug的展示代码:
c=[0,1,2,3]
for i in c:
print i
c.remove(i)
#output:
#0
#2
View Code
二十、职责链模式
模式特点:使多个对象都有机会处理请求,从而避免发送者和接收者的耦合关系。将对象连成链并沿着这条链传递请求直到被处理。
程序实例:请假和加薪等请求发给上级,如果上级无权决定,那么递交给上级的上级。
代码特点:无
class Request:
def __init__(self,tcontent,tnum):
self.content = tcontent
self.num = tnum
class Manager:
def __init__(self,temp):
self.name = temp
def SetSuccessor(self,temp):
self.manager = temp
def GetRequest(self,req):
pass
class CommonManager(Manager):
def GetRequest(self,req):
if(req.num>=0 and req.num<10):
print "%s handled %d request." %(self.name,req.num)
else:
self.manager.GetRequest(req)
class MajorDomo(Manager):
def GetRequest(self,req):
if(req.num>=10):
print "%s handled %d request." %(self.name,req.num)
if __name__ == "__main__":
common = CommonManager("Zhang")
major = MajorDomo("Lee")
common.SetSuccessor(major)
req = Request("rest",33)
common.GetRequest(req)
req2 = Request("salary",3)
common.GetRequest(req2)
View Code
二十一、中介者模式
模式特点:用一个对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互。
程序实例:两个对象通过中介者相互通信
代码特点:无
class Mediator:
def Send(self,message,col):
pass
class Colleague:
def __init__(self,temp):
self.mediator = temp
class Colleague1(Colleague):
def Send(self,message):
self.mediator.Send(message,self)
def Notify(self,message):
print "Colleague1 get a message:%s" %message
class Colleague2(Colleague):
def Send(self,message):
self.mediator.Send(message,self)
def Notify(self,message):
print "Colleague2 get a message:%s" %message
class ConcreteMediator(Mediator):
def Send(self,message,col):
if(col==col1):
col2.Notify(message)
else:
col1.Notify(message)
if __name__ == "__main__":
m =ConcreteMediator()
col1 = Colleague1(m)
col2 = Colleague1(m)
m.col1=col1
m.col2=col2
col1.Send("How are you?");
col2.Send("Fine.");
View Code
二十二、享元模式
模式特点:运用共享技术有效地支持大量细粒度的对象。
程序实例:一个网站工厂,根据用户请求的类别返回相应类别的网站。如果这种类别的网站已经在服务器上,那么返回这种网站并加上不同用户的独特的数据;如果没有,那么生成一个。
代码特点:为了展示每种网站的由用户请求的次数,这里为它们建立了一个引用次数的字典。
之所以不用Python的sys模块中的sys.getrefcount()方法统计引用计数是因为有的对象可能在别处被隐式的引用,从而增加了引用计数。
import sys
class WebSite:
def Use(self):
pass
class ConcreteWebSite(WebSite):
def __init__(self,strName):
self.name = strName
def Use(self,user):
print "Website type:%s,user:%s" %(self.name,user)
class UnShareWebSite(WebSite):
def __init__(self,strName):
self.name = strName
def Use(self,user):
print "UnShare Website type:%s,user:%s" %(self.name, user)
class WebFactory:
def __init__(self):
test = ConcreteWebSite("test")
self.webtype ={"test":test}
self.count = {"test":0}
def GetWeb(self,webtype):
if webtype not in self.webtype:
temp = ConcreteWebSite(webtype)
self.webtype[webtype] = temp
self.count[webtype] =1
else:
temp = self.webtype[webtype]
self.count[webtype] = self.count[webtype]+1
return temp
def GetCount(self):
for key in self.webtype:
#print "type: %s, count:%d" %(key,sys.getrefcount(self.webtype[key]))
print "type: %s, count:%d " %(key,self.count[key])
if __name__ == "__main__":
f = WebFactory()
ws=f.GetWeb("blog")
ws.Use("Lee")
ws2=f.GetWeb("show")
ws2.Use("Jack")
ws3=f.GetWeb("blog")
ws3.Use("Chen")
ws4=UnShareWebSite("TEST")
ws4.Use("Mr.Q")
print f.webtype
f.GetCount()
View Code
二十三、解释器模式
模式特点:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
程序实例:(只是模式特点的最简单示范)
代码特点:无
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)
View Code
二十四、访问者模式
模式特点:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
程序实例:对于男人和女人(接受访问者的元素,ObjectStructure用于穷举这些元素),不同的遭遇(具体的访问者)引发两种对象的不同行为。
代码特点:无
1 # -*- coding: UTF-8 -*-
2 class Person:
3 def Accept(self,visitor):
4 pass
5
6 class Man(Person):
7 def Accept(self,visitor):
8 visitor.GetManConclusion(self)
9
10 class Woman(Person):
11 def Accept(self,visitor):
12 visitor.GetWomanConclusion(self)
13
14 class Action:
15 def GetManConclusion(self,concreteElementA):
16 pass
17 def GetWomanConclusion(self,concreteElementB):
18 pass
19
20 class Success(Action):
21 def GetManConclusion(self,concreteElementA):
22 print "男人成功时,背后有个伟大的女人"
23 def GetWomanConclusion(self,concreteElementB):
24 print "女人成功时,背后有个不成功的男人"
25
26 class Failure(Action):
27 def GetManConclusion(self,concreteElementA):
28 print "男人失败时,闷头喝酒,谁也不用劝"
29 def GetWomanConclusion(self,concreteElementB):
30 print "女人失败时,眼泪汪汪,谁也劝不了"
31
32
33 class ObjectStructure:
34 def __init__(self):
35 self.plist=[]
36 def Add(self,p):
37 self.plist=self.plist+[p]
38 def Display(self,act):
39 for p in self.plist:
40 p.Accept(act)
41
42 if __name__ == "__main__":
43 os = ObjectStructure()
44 os.Add(Man())
45 os.Add(Woman())
46 sc = Success()
47 os.Display(sc)
48 fl = Failure()
49 os.Display(fl)
View Code