上一周把《大话设计模式》看完了,对面向对象技术有了新的理解,对于一个在C下写代码比较多、偶尔会用到一些脚本语言写脚本的人来说,很是开阔眼界。《大话设计模式》的代码使用C#写成的,而在本人接触到的面向对象语言中,只对C++和Python还算了解,为了加深对各个模式的理解,我在网上下载了一个C++版的源代码,并根据自己的理解边读这本书边动手实践C++源代码,同时将其改写成了Python代码,算是一箭三雕吧。
由于这些代码的目的是展示各个设计模式而非完成一个具体的复杂任务,基于C++版本改写,例子的取材也和《大话设计模式》基本相同,再加上个人水平有限,因此这些Python版代码写的比较简单,虽然能跑起来是不假,不过难免有bug,而且实现也不一定最优,C++的味道比较浓而不够pythonic,还请高手包容指正。不过我还是尽量把或多或少有些pythonic的东西放在每个模式的“代码特点”部分进行展示,而这个“代码特点”里也不仅仅是pythonic的东西。
使用Python版本为2.6。
配图同样摘自《大话设计模式》,因此是C#风格的UML类图,为了便于排版已经缩小了。
一、简单工厂模式
模式特点:工厂根据条件产生不同功能的类。
程序实例:四则运算计算器,根据用户的输入产生相应的运算类,用这个运算类处理具体的运算。
代码特点:C/C++中的switch...case...分支使用字典的方式代替。
使用异常机制对除数为0的情况进行处理。
class Operation: def GetResult(self): passclass OperationAdd(Operation):
def GetResult(self):
return self.op1+self.op2class OperationSub(Operation):
def GetResult(self):
return self.op1-self.op2class OperationMul(Operation):
def GetResult(self):
return self.op1*self.op2class OperationDiv(Operation):
def GetResult(self):
try:
result = self.op1/self.op2
return result
except:
print "error:divided by zero."
return 0class OperationUndef(Operation):
def GetResult(self):
print "Undefine operation."
return 0class OperationFactory:
operation = {}
operation["+"] = OperationAdd();
operation["-"] = OperationSub();
operation["*"] = OperationMul();
operation["/"] = OperationDiv();
def createOperation(self,ch):
if ch in self.operation:
op = self.operation[ch]
else:
op = OperationUndef()
return opif name == "main":
op = raw_input("operator: ")
opa = input("a: ")
opb = input("b: ")
factory = OperationFactory()
cal = factory.createOperation(op)
cal.op1 = opa
cal.op2 = opb
print cal.GetResult()
二、策略模式
模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端。
程序实例:商场收银软件,需要根据不同的销售策略方式进行收费
代码特点:不同于同例1,这里使用字典是为了避免关键字不在字典导致bug的陷阱。
class CashSuper: def AcceptCash(self,money): return 0class CashNormal(CashSuper):
def AcceptCash(self,money):
return moneyclass CashRebate(CashSuper):
discount = 0
def init(self,ds):
self.discount = ds
def AcceptCash(self,money):
return money * self.discountclass CashReturn(CashSuper):
total = 0;
ret = 0;
def init(self,t,r):
self.total = t
self.ret = r
def AcceptCash(self,money):
if (money>=self.total):
return money - self.ret
else:
return moneyclass CashContext:
def init(self,csuper):
self.cs = csuper
def GetResult(self,money):
return self.cs.AcceptCash(money)if name == "main":
money = input("money:")
strategy = {}
strategy[1] = CashContext(CashNormal())
strategy[2] = CashContext(CashRebate(0.8))
strategy[3] = CashContext(CashReturn(300,100))
ctype = input("type:[1]for normal,[2]for 80% discount [3]for 300 -100.")
if ctype in strategy:
cc = strategy[ctype]
else:
print "Undefine type.Use normal mode."
cc = strategy[1]
print "you will pay:%d" %(cc.GetResult(money))
三、装饰模式
模式特点:动态地为对象增加额外的职责
程序实例:展示一个人一件一件穿衣服的过程。
代码特点:无
class Person: def __init__(self,tname): self.name = tname def Show(self): print "dressed %s" %(self.name)class Finery(Person):
componet = None
def init(self):
pass
def Decorate(self,ct):
self.componet = ct
def Show(self):
if(self.componet!=None):
self.componet.Show()class TShirts(Finery):
def init(self):
pass
def Show(self):
print "Big T-shirt "
self.componet.Show()class BigTrouser(Finery):
def init(self):
pass
def Show(self):
print "Big Trouser "
self.componet.Show()if name == "main":
p = Person("somebody")
bt = BigTrouser()
ts = TShirts()
bt.Decorate(p)
ts.Decorate(bt)
ts.Show()
四、代理模式
模式特点:为其他对象提供一种代理以控制对这个对象的访问。
程序实例:同模式特点描述。
代码特点:无
class Interface : def Request(self): return 0class RealSubject(Interface):
def Request(self):
print "Real request."class Proxy(Interface):
def Request(self):
self.real = RealSubject()
self.real.Request()if name == "main":
p = Proxy()
p.Request()
五、工厂方法模式
模式特点:定义一个用于创建对象的接口,让子类决定实例化哪一个类。这使得一个类的实例化延迟到其子类。
程序实例:基类雷锋类,派生出学生类和志愿者类,由这两种子类完成“学雷锋”工作。子类的创建由雷锋工厂的对应的子类完成。
代码特点:无
class LeiFeng: def Sweep(self): print "LeiFeng sweep"class Student(LeiFeng):
def Sweep(self):
print "Student sweep"class Volenter(LeiFeng):
def Sweep(self):
print "Volenter sweep"class LeiFengFactory:
def CreateLeiFeng(self):
temp = LeiFeng()
return tempclass StudentFactory(LeiFengFactory):
def CreateLeiFeng(self):
temp = Student()
return tempclass VolenterFactory(LeiFengFactory):
def CreateLeiFeng(self):
temp = Volenter()
return tempif name == "main":
sf = StudentFactory()
s=sf.CreateLeiFeng()
s.Sweep()
sdf = VolenterFactory()
sd=sdf.CreateLeiFeng()
sd.Sweep()
六、原型模式
模式特点:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
程序实例:从简历原型,生成新的简历
代码特点:简历类Resume提供的Clone()方法其实并不是真正的Clone,只是为已存在对象增加了一次引用。
Python为对象提供的copy模块中的copy方法和deepcopy方法已经实现了原型模式,但由于例子的层次较浅,二者看不出区别。
import copy class WorkExp: place="" year=0class Resume:
name = \'\'
age = 0
def init(self,n):
self.name = n
def SetAge(self,a):
self.age = a
def SetWorkExp(self,p,y):
self.place = p
self.year = y
def Display(self):
print self.age
print self.place
print self.year
def Clone(self):
#实际不是“克隆”,只是返回了自身
return selfif name == "main":
a = Resume("a")
b = a.Clone()
c = copy.copy(a)
d = copy.deepcopy(a)
a.SetAge(7)
b.SetAge(12)
c.SetAge(15)
d.SetAge(18)
a.SetWorkExp("PrimarySchool",1996)
b.SetWorkExp("MidSchool",2001)
c.SetWorkExp("HighSchool",2004)
d.SetWorkExp("University",2007)
a.Display()
b.Display()
c.Display()
d.Display()
七、模板方法模式
模式特点:定义一个操作中的算法骨架,将一些步骤延迟至子类中。
程序实例:考试时使用同一种考卷(父类),不同学生上交自己填写的试卷(子类方法的实现)
代码特点:无
class TestPaper: def TestQuestion1(self): print "Test1:A. B. C. D." print "(%s)" %self.Answer1()</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> TestQuestion2(self): </span><span style="color: #0000ff;">print</span> <span style="color: #800000;">"</span><span style="color: #800000;">Test1:A. B. C. D.</span><span style="color: #800000;">"</span> <span style="color: #0000ff;">print</span> <span style="color: #800000;">"</span><span style="color: #800000;">(%s)</span><span style="color: #800000;">"</span> %<span style="color: #000000;">self.Answer2() </span><span style="color: #0000ff;">def</span><span style="color: #000000;"> Answer1(self): </span><span style="color: #0000ff;">return</span> <span style="color: #800000;">""</span> <span style="color: #0000ff;">def</span><span style="color: #000000;"> Answer2(self): </span><span style="color: #0000ff;">return</span> <span style="color: #800000;">""</span>
class TestPaperA(TestPaper):
def Answer1(self):
return "B"
def Answer2(self):
return "C";class TestPaperB(TestPaper):
def Answer1(self):
return "D"
def Answer2(self):
return "D";if name == "main":
s1 = TestPaperA()
s2 = TestPaperB()
print "student 1"
s1.TestQuestion1()
s1.TestQuestion2()
print "student 2"
s2.TestQuestion1()
s2.TestQuestion2()
八、外观模式
模式特点:为一组调用提供一致的接口。
程序实例:接口将几种调用分别组合成为两组,用户通过接口调用其中的一组。
代码特点:无
class SubSystemOne: def MethodOne(self): print "SubSysOne"class SubSystemTwo:
def MethodTwo(self):
print "SubSysTwo"class SubSystemThree:
def MethodThree(self):
print "SubSysThree"class SubSystemFour:
def MethodFour(self):
print "SubSysFour"class Facade:
def init(self):
self.one = SubSystemOne()
self.two = SubSystemTwo()
self.three = SubSystemThree()
self.four = SubSystemFour()
def MethodA(self):
print "MethodA"
self.one.MethodOne()
self.two.MethodTwo()
self.four.MethodFour()
def MethodB(self):
print "MethodB"
self.two.MethodTwo()
self.three.MethodThree()if name == "main":
facade = Facade()
facade.MethodA()
facade.MethodB()
九、建造者模式
模式特点:将一个复杂对象的构建(Director)与它的表示(Builder)分离,使得同样的构建过程可以创建不同的表示(ConcreteBuilder)。
程序实例:“画”出一个四肢健全(头身手腿)的小人
代码特点:无
class Person: def CreateHead(self): pass def CreateHand(self): pass def CreateBody(self): pass def CreateFoot(self): passclass ThinPerson(Person):
def CreateHead(self):
print "thin head"
def CreateHand(self):
print "thin hand"
def CreateBody(self):
print "thin body"
def CreateFoot(self):
print "thin foot"class ThickPerson(Person):
def CreateHead(self):
print "thick head"
def CreateHand(self):
print "thick hand"
def CreateBody(self):
print "thick body"
def CreateFoot(self):
print "thick foot"class Director:
def init(self,temp):
self.p = temp
def Create(self):
self.p.CreateHead()
self.p.CreateBody()
self.p.CreateHand()
self.p.CreateFoot()if name == "main":
p = ThickPerson()
d = Director(p)
d.Create()
十、观察者模式
模式特点:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,当主题对象状态发生变化时会通知所有观察者。
程序实例:公司里有两种上班时趁老板不在时偷懒的员工:看NBA的和看股票行情的,并且事先让老板秘书当老板出现时通知他们继续做手头上的工作。
程序特点:无
class Observer: def __init__(self,strname,strsub): self.name = strname self.sub = strsub def Update(self): passclass StockObserver(Observer):
#no need to rewrite init()
def Update(self):
print "%s:%s,stop watching Stock and go on work!" %(self.name,self.sub.action)class NBAObserver(Observer):
def Update(self):
print "%s:%s,stop watching NBA and go on work!" %(self.name,self.sub.action)class SecretaryBase:
def init(self):
self.observers = []
def Attach(self,new_observer):
pass
def Notify(self):
passclass Secretary(SecretaryBase):
def Attach(self,new_observer):
self.observers.append(new_observer)
def Notify(self):
for p in self.observers:
p.Update()if name == "main":
p = Secretary()
s1 = StockObserver("xh",p)
s2 = NBAObserver("wyt",p)
p.Attach(s1);
p.Attach(s2);
p.action = "WARNING:BOSS ";
p.Notify()
十一、抽象工厂模式
模式特点:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类。
程序实例:提供对不同的数据库访问的支持。
IUser和IDepartment是两种不同的抽象产品,它们都有Access和SQL Server这两种不同的实现;IFactory是产生IUser和IDepartment的抽象工厂,根据具体实现(AccessFactory和SqlFactory)产生对应的具体的对象(CAccessUser与CAccessDepartment,或者CSqlUser与CSqlDepartment)。
代码特点:无
class IUser: def GetUser(self): pass def InsertUser(self): passclass IDepartment:
def GetDepartment(self):
pass
def InsertDepartment(self):
passclass CAccessUser(IUser):
def GetUser(self):
print "Access GetUser"
def InsertUser(self):
print "Access InsertUser"class CAccessDepartment(IDepartment):
def GetDepartment(self):
print "Access GetDepartment"
def InsertDepartment(self):
print "Access InsertDepartment"class CSqlUser(IUser):
def GetUser(self):
print "Sql GetUser"
def InsertUser(self):
print "Sql InsertUser"class CSqlDepartment(IDepartment):
def GetDepartment(self):
print "Sql GetDepartment"
def InsertDepartment(self):
print "Sql InsertDepartment"class IFactory:
def CreateUser(self):
pass
def CreateDepartment(self):
passclass AccessFactory(IFactory):
def CreateUser(self):
temp=CAccessUser()
return temp
def CreateDepartment(self):
temp = CAccessDepartment()
return tempclass SqlFactory(IFactory):
def CreateUser(self):
temp = CSqlUser()
return temp
def CreateDepartment(self):
temp = CSqlDepartment()
return tempif name == "main":
factory = SqlFactory()
user=factory.CreateUser()
depart=factory.CreateDepartment()
user.GetUser()
depart.GetDepartment()
十二、状态模式
模式特点:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
程序实例:描述一个程序员的工作状态,当需要改变状态时发生改变,不同状态下的方法实现不同
代码特点:无
class State: def WirteProgram(self): passclass Work:
def init(self):
self.hour = 9
self.current = ForenoonState()
def SetState(self,temp):
self.current = temp
def WriteProgram(self):
self.current.WriteProgram(self)class NoonState(State):
def WriteProgram(self,w):
print "noon working"
if (w.hour<13):
print "fun."
else:
print "need to rest.大话设计模式-外观模式(大鸟和小菜java版)