《大话设计模式》Python版代码实现

开发 后端 前端
《大话设计模式》的代码使用C#写成的,而在本人接触到的面向对象语言中,只对C++和Python还算了解,为了加深对各个模式的理解,将其改写成了Python代码

上一周把《大话设计模式》看完了,对面向对象技术有了新的理解,对于一个在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. 简单工厂模式   
  2.  
  3. class Operation:  
  4.     def GetResult(self):  
  5.         pass 
  6.  
  7. class OperationAdd(Operation):  
  8.     def GetResult(self):  
  9.         return self.op1+self.op2  
  10.  
  11.  
  12. class OperationSub(Operation):  
  13.     def GetResult(self):  
  14.         return self.op1-self.op2  
  15.  
  16.  
  17. class OperationMul(Operation):  
  18.     def GetResult(self):  
  19.         return self.op1*self.op2  
  20.  
  21.  
  22. class OperationDiv(Operation):  
  23.     def GetResult(self):  
  24.         try:  
  25.             result = self.op1/self.op2  
  26.             return result  
  27.         except:  
  28.             print "error:divided by zero." 
  29.             return 0 
  30.  
  31. class OperationUndef(Operation):  
  32.     def GetResult(self):  
  33.         print "Undefine operation." 
  34.         return 0 
  35.  
  36. class OperationFactory:  
  37.     operation = {}  
  38.     operation["+"] = OperationAdd();  
  39.     operation["-"] = OperationSub();  
  40.     operation["*"] = OperationMul();  
  41.     operation["/"] = OperationDiv();  
  42.     def createOperation(self,ch):          
  43.         if ch in self.operation:  
  44.             op = self.operation[ch]  
  45.         else:  
  46.             op = OperationUndef()  
  47.         return op  
  48.  
  49. if __name__ == "__main__":  
  50.     op = raw_input("operator: ")  
  51.     opa = input("a: ")  
  52.     opb = input("b: ")  
  53.     factory = OperationFactory()  
  54.     cal = factory.createOperation(op)  
  55.     cal.op1 = opa  
  56.     cal.op2 = opb  
  57.     print cal.GetResult() 

二、策略模式

模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端。

程序实例:商场收银软件,需要根据不同的销售策略方式进行收费

代码特点:不同于同例1,这里使用字典是为了避免关键字不在字典导致bug的陷阱。

  1. 策略模式   
  2.  
  3. class CashSuper:  
  4.     def AcceptCash(self,money):  
  5.         return 0 
  6.  
  7. class CashNormal(CashSuper):  
  8.     def AcceptCash(self,money):  
  9.         return money  
  10.  
  11. class CashRebate(CashSuper):  
  12.     discount = 0 
  13.     def __init__(self,ds):  
  14.         self.discount = ds  
  15.     def AcceptCash(self,money):  
  16.         return money * self.discount  
  17.  
  18. class CashReturn(CashSuper):  
  19.     total = 0;  
  20.     ret = 0;  
  21.     def __init__(self,t,r):  
  22.         self.total = t  
  23.         self.ret = r  
  24.     def AcceptCash(self,money):  
  25.         if (money>=self.total):  
  26.             return money - self.ret  
  27.         else:  
  28.             return money  
  29.  
  30. class CashContext:  
  31.     def __init__(self,csuper):  
  32.         self.cs = csuper  
  33.     def GetResult(self,money):  
  34.         return self.cs.AcceptCash(money)  
  35.  
  36. if __name__ == "__main__":  
  37.     money = input("money:")  
  38.     strategy = {}  
  39.     strategy[1] = CashContext(CashNormal())  
  40.     strategy[2] = CashContext(CashRebate(0.8))  
  41.     strategy[3] = CashContext(CashReturn(300,100))  
  42.     ctype = input("type:[1]for normal,[2]for 80% discount [3]for 300 -100.")  
  43.     if ctype in strategy:  
  44.         cc = strategy[ctype]  
  45.     else:  
  46.         print "Undefine type.Use normal mode." 
  47.         cc = strategy[1]  
  48.     print "you will pay:%d" %(cc.GetResult(money)) 

三、装饰模式

模式特点:动态地为对象增加额外的职责

程序实例:展示一个人一件一件穿衣服的过程。

代码特点:无

  1. 装饰模式   
  2.  
  3. class Person:  
  4.     def __init__(self,tname):  
  5.         self.name = tname  
  6.     def Show(self):  
  7.        print "dressed %s" %(self.name)  
  8.  
  9. class Finery(Person):  
  10.     componet = None 
  11.     def __init__(self):  
  12.         pass 
  13.     def Decorate(self,ct):  
  14.         self.componet = ct  
  15.     def Show(self):  
  16.     if(self.componet!=None):  
  17.         self.componet.Show()  
  18.  
  19. class TShirts(Finery):  
  20.     def __init__(self):  
  21.         pass 
  22.     def Show(self):  
  23.         print "Big T-shirt " 
  24.         self.componet.Show()  
  25.  
  26. class BigTrouser(Finery):  
  27.     def __init__(self):  
  28.         pass 
  29.     def Show(self):  
  30.         print "Big Trouser " 
  31.         self.componet.Show()  
  32.  
  33. if __name__ == "__main__":  
  34.     p = Person("somebody")  
  35.     bt = BigTrouser()  
  36.     ts = TShirts()  
  37.     bt.Decorate(p)  
  38.     ts.Decorate(bt)  
  39.     ts.Show() 

四、代理模式

模式特点:为其他对象提供一种代理以控制对这个对象的访问。

程序实例:同模式特点描述。

代码特点:无

  1. 代理模式   
  2.  
  3. class Interface :  
  4.     def Request(self):  
  5.     return 0 
  6.  
  7. class RealSubject(Interface):   
  8.     def Request(self):  
  9.         print "Real request." 
  10.  
  11. class Proxy(Interface):  
  12.     def Request(self):  
  13.         self.real = RealSubject()  
  14.         self.real.Request()  
  15.  
  16. if __name__ == "__main__":  
  17.     p = Proxy()  
  18.     p.Request() 

五、工厂方法模式

模式特点:定义一个用于创建对象的接口,让子类决定实例化哪一个类。这使得一个类的实例化延迟到其子类。

程序实例:基类雷锋类,派生出学生类和志愿者类,由这两种子类完成“学雷锋”工作。子类的创建由雷锋工厂的对应的子类完成。

代码特点:无

  1. 工厂方法模式   
  2.  
  3. class LeiFeng:  
  4.     def Sweep(self):  
  5.         print "LeiFeng sweep" 
  6.  
  7. class Student(LeiFeng):  
  8.     def Sweep(self):  
  9.         print "Student sweep" 
  10.  
  11. class Volenter(LeiFeng):  
  12.     def Sweep(self):  
  13.         print "Volenter sweep" 
  14.  
  15. class LeiFengFactory:  
  16.     def CreateLeiFeng(self):  
  17.         temp = LeiFeng()  
  18.         return temp  
  19.  
  20. class StudentFactory(LeiFengFactory):  
  21.     def CreateLeiFeng(self):  
  22.         temp = Student()  
  23.         return temp  
  24.  
  25. class VolenterFactory(LeiFengFactory):  
  26.     def CreateLeiFeng(self):  
  27.         temp = Volenter()  
  28.         return temp  
  29.  
  30. if __name__ == "__main__":  
  31.     sf = StudentFactory()  
  32.     s=sf.CreateLeiFeng()  
  33.     s.Sweep()  
  34.     sdf = VolenterFactory()  
  35.     sd=sdf.CreateLeiFeng()  
  36.     sd.Sweep() 

#p#

六、原型模式

模式特点:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

程序实例:从简历原型,生成新的简历

代码特点:简历类Resume提供的Clone()方法其实并不是真正的Clone,只是为已存在对象增加了一次引用。

Python为对象提供的copy模块中的copy方法和deepcopy方法已经实现了原型模式,但由于例子的层次较浅,二者看不出区别。

  1. 原型模式   
  2.  
  3. import copy  
  4. class WorkExp:  
  5.     place=""  
  6.     year=0 
  7.  
  8. class Resume:  
  9.     name = '' 
  10.     age = 0 
  11.     def __init__(self,n):  
  12.         self.name = n  
  13.     def SetAge(self,a):  
  14.         self.age = a  
  15.     def SetWorkExp(self,p,y):  
  16.         self.place = p  
  17.         self.year = y  
  18.     def Display(self):  
  19.         print self.age  
  20.         print self.place  
  21.         print self.year  
  22.     def Clone(self):  
  23.     #实际不是“克隆”,只是返回了自身  
  24.         return self 
  25.  
  26. if __name__ == "__main__":  
  27.     a = Resume("a")  
  28.     b = a.Clone()  
  29.     c = copy.copy(a)  
  30.     d = copy.deepcopy(a)  
  31.     a.SetAge(7)  
  32.     b.SetAge(12)  
  33.     c.SetAge(15)  
  34.     d.SetAge(18)  
  35.     a.SetWorkExp("PrimarySchool",1996)  
  36.     b.SetWorkExp("MidSchool",2001)  
  37.     c.SetWorkExp("HighSchool",2004)  
  38.     d.SetWorkExp("University",2007)  
  39.     a.Display()  
  40.     b.Display()  
  41.     c.Display()  
  42.     d.Display() 

七、模板方法模式

模式特点:定义一个操作中的算法骨架,将一些步骤延迟至子类中。

程序实例:考试时使用同一种考卷(父类),不同学生上交自己填写的试卷(子类方法的实现)

代码特点:无

  1. 模板方法模式   
  2.  
  3. class TestPaper:  
  4.     def TestQuestion1(self):  
  5.         print "Test1:A. B. C. D." 
  6.         print "(%s)" %self.Answer1()  
  7.  
  8.     def TestQuestion2(self):  
  9.         print "Test1:A. B. C. D." 
  10.         print "(%s)" %self.Answer2()  
  11.     def Answer1(self):  
  12.         return ""  
  13.     def Answer2(self):  
  14.         return ""  
  15.  
  16. class TestPaperA(TestPaper):  
  17.     def Answer1(self):  
  18.         return "B" 
  19.     def Answer2(self):  
  20.         return "C";  
  21.  
  22. class TestPaperB(TestPaper):  
  23.     def Answer1(self):  
  24.         return "D" 
  25.     def Answer2(self):  
  26.         return "D";  
  27.  
  28. if __name__ == "__main__":  
  29.     s1 = TestPaperA()  
  30.     s2 = TestPaperB()  
  31.     print "student 1" 
  32.     s1.TestQuestion1()  
  33.     s1.TestQuestion2()  
  34.     print "student 2" 
  35.     s2.TestQuestion1()  
  36.     s2.TestQuestion2() 

八、外观模式

模式特点:为一组调用提供一致的接口。

程序实例:接口将几种调用分别组合成为两组,用户通过接口调用其中的一组。

代码特点:无

  1. 外观模式   
  2.  
  3. class SubSystemOne:  
  4.     def MethodOne(self):  
  5.         print "SubSysOne" 
  6.  
  7. class SubSystemTwo:  
  8.     def MethodTwo(self):  
  9.         print "SubSysTwo" 
  10.  
  11. class SubSystemThree:  
  12.     def MethodThree(self):  
  13.         print "SubSysThree" 
  14.  
  15. class SubSystemFour:  
  16.     def MethodFour(self):  
  17.         print "SubSysFour" 
  18.  
  19.  
  20. class Facade:  
  21.     def __init__(self):  
  22.         self.one = SubSystemOne()  
  23.         self.two = SubSystemTwo()  
  24.         self.three = SubSystemThree()  
  25.         self.four = SubSystemFour()  
  26.     def MethodA(self):  
  27.         print "MethodA" 
  28.         self.one.MethodOne()  
  29.         self.two.MethodTwo()  
  30.         self.four.MethodFour()  
  31.     def MethodB(self):  
  32.         print "MethodB" 
  33.         self.two.MethodTwo()  
  34.         self.three.MethodThree()  
  35.  
  36. if __name__ == "__main__":  
  37.     facade = Facade()  
  38.     facade.MethodA()  
  39.     facade.MethodB() 

九、建造者模式

模式特点:将一个复杂对象的构建(Director)与它的表示(Builder)分离,使得同样的构建过程可以创建不同的表示(ConcreteBuilder)。

程序实例:“画”出一个四肢健全(头身手腿)的小人

代码特点:无

  1. 建造者模式   
  2.  
  3. class Person:  
  4.     def CreateHead(self):  
  5.         pass 
  6.     def CreateHand(self):  
  7.         pass 
  8.     def CreateBody(self):  
  9.         pass 
  10.     def CreateFoot(self):  
  11.         pass 
  12.  
  13. class ThinPerson(Person):  
  14.     def CreateHead(self):  
  15.         print "thin head" 
  16.     def CreateHand(self):  
  17.         print "thin hand" 
  18.     def CreateBody(self):  
  19.         print "thin body" 
  20.     def CreateFoot(self):  
  21.         print "thin foot" 
  22.  
  23. class ThickPerson(Person):  
  24.     def CreateHead(self):  
  25.         print "thick head" 
  26.     def CreateHand(self):  
  27.         print "thick hand" 
  28.     def CreateBody(self):  
  29.         print "thick body" 
  30.     def CreateFoot(self):  
  31.         print "thick foot" 
  32.  
  33. class Director:  
  34.     def __init__(self,temp):  
  35.         self.p = temp  
  36.     def Create(self):  
  37.         self.p.CreateHead()  
  38.         self.p.CreateBody()  
  39.         self.p.CreateHand()  
  40.         self.p.CreateFoot()  
  41.  
  42. if __name__ == "__main__":  
  43.     p = ThickPerson()  
  44.     d = Director(p)  
  45.     d.Create() 

十、观察者模式

模式特点:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,当主题对象状态发生变化时会通知所有观察者。

程序实例:公司里有两种上班时趁老板不在时偷懒的员工:看NBA的和看股票行情的,并且事先让老板秘书当老板出现时通知他们继续做手头上的工作。

程序特点:无

  1. 观察者模式   
  2.  
  3. class Observer:  
  4.     def __init__(self,strname,strsub):  
  5.         self.name = strname  
  6.         self.sub = strsub  
  7.     def Update(self):  
  8.         pass 
  9.  
  10. class StockObserver(Observer):  
  11.     #no need to rewrite __init__()  
  12.     def Update(self):  
  13.         print "%s:%s,stop watching Stock and go on work!" %(self.name,self.sub.action)  
  14.  
  15. class NBAObserver(Observer):  
  16.     def Update(self):  
  17.         print "%s:%s,stop watching NBA and go on work!" %(self.name,self.sub.action)  
  18.  
  19. class SecretaryBase:  
  20.     def __init__(self):  
  21.         self.observers = []  
  22.     def Attach(self,new_observer):  
  23.         pass   
  24.     def Notify(self):  
  25.         pass 
  26.  
  27. class Secretary(SecretaryBase):  
  28.     def Attach(self,new_observer):  
  29.         self.observers.append(new_observer)  
  30.     def Notify(self):  
  31.         for p in self.observers:  
  32.             p.Update()  
  33.  
  34. if __name__ == "__main__":  
  35.     p = Secretary()  
  36.     s1 = StockObserver("xh",p)  
  37.     s2 = NBAObserver("wyt",p)  
  38.     p.Attach(s1);  
  39.     p.Attach(s2);  
  40.     p.action = "WARNING:BOSS ";  
  41.     p.Notify() 

#p#

十一、抽象工厂模式

模式特点:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的类。

程序实例:提供对不同的数据库访问的支持。

IUser和IDepartment是两种不同的抽象产品,它们都有Access和SQL Server这两种不同的实现;IFactory是产生IUser和IDepartment的抽象工厂,根据具体实现(AccessFactory和SqlFactory)产生对应的具体的对象(CAccessUser与CAccessDepartment,或者CSqlUser与CSqlDepartment)。

代码特点:无

  1. 抽象工厂模式   
  2.  
  3. class IUser:  
  4.     def GetUser(self):  
  5.         pass 
  6.     def InsertUser(self):  
  7.         pass 
  8.  
  9. class IDepartment:  
  10.     def GetDepartment(self):  
  11.         pass 
  12.     def InsertDepartment(self):  
  13.         pass 
  14.  
  15. class CAccessUser(IUser):  
  16.     def GetUser(self):  
  17.         print "Access GetUser" 
  18.     def InsertUser(self):  
  19.         print "Access InsertUser" 
  20.  
  21.  
  22. class CAccessDepartment(IDepartment):  
  23.     def GetDepartment(self):  
  24.         print "Access GetDepartment" 
  25.     def InsertDepartment(self):  
  26.         print "Access InsertDepartment" 
  27.  
  28. class CSqlUser(IUser):  
  29.     def GetUser(self):  
  30.         print "Sql GetUser" 
  31.     def InsertUser(self):  
  32.         print "Sql InsertUser" 
  33.  
  34.  
  35. class CSqlDepartment(IDepartment):  
  36.     def GetDepartment(self):  
  37.         print "Sql GetDepartment" 
  38.     def InsertDepartment(self):  
  39.         print "Sql InsertDepartment" 
  40.  
  41. class IFactory:  
  42.     def CreateUser(self):  
  43.         pass 
  44.     def CreateDepartment(self):  
  45.         pass 
  46.  
  47. class AccessFactory(IFactory):  
  48.     def CreateUser(self):  
  49.         temp=CAccessUser()  
  50.         return temp  
  51.     def CreateDepartment(self):  
  52.         temp = CAccessDepartment()  
  53.         return temp  
  54.  
  55. class SqlFactory(IFactory):  
  56.     def CreateUser(self):  
  57.         temp = CSqlUser()  
  58.         return temp  
  59.     def CreateDepartment(self):  
  60.         temp = CSqlDepartment()  
  61.         return temp  
  62.  
  63. if __name__ == "__main__":  
  64.     factory = SqlFactory()  
  65.     user=factory.CreateUser()  
  66.     depart=factory.CreateDepartment()  
  67.     user.GetUser()  
  68.     depart.GetDepartment() 

十二、状态模式

模式特点:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

程序实例:描述一个程序员的工作状态,当需要改变状态时发生改变,不同状态下的方法实现不同

代码特点:无

  1. 状态模式   
  2.  
  3. class State:  
  4.     def WirteProgram(self):  
  5.         pass 
  6.  
  7. class Work:  
  8.     def __init__(self):  
  9.         self.hour = 9 
  10.         self.current = ForenoonState()  
  11.     def SetState(self,temp):  
  12.         self.current = temp  
  13.     def WriteProgram(self):  
  14.         self.current.WriteProgram(self)  
  15.  
  16. class NoonState(State):  
  17.     def WriteProgram(self,w):  
  18.         print "noon working" 
  19.         if (w.hour<13):  
  20.             print "fun." 
  21.         else:  
  22.             print "need to rest." 
  23.  
  24. class ForenoonState(State):  
  25.     def WriteProgram(self,w):  
  26.         if (w.hour<12):  
  27.             print "morning working" 
  28.             print "energetic" 
  29.         else:  
  30.             w.SetState(NoonState())          
  31.             w.WriteProgram()  
  32.  
  33. if __name__ == "__main__":  
  34.     mywork = Work()  
  35.     mywork.hour = 9 
  36.     mywork.WriteProgram()  
  37.     mywork.hour =14 
  38.     mywork.WriteProgram() 

十三、适配器模式

模式特点:将一个类的接口转换成为客户希望的另外一个接口。

程序实例:用户通过适配器使用一个类的方法。

代码特点:无

  1. 适配器模式   
  2.  
  3. class Target:  
  4.     def Request():  
  5.         print "common request." 
  6.  
  7. class Adaptee(Target):  
  8.     def SpecificRequest(self):  
  9.         print "specific request." 
  10.  
  11. class Adapter(Target):  
  12.     def __init__(self,ada):  
  13.         self.adaptee = ada  
  14.     def Request(self):  
  15.         self.adaptee.SpecificRequest()  
  16.  
  17. if __name__ == "__main__":  
  18.     adaptee = Adaptee()  
  19.     adapter = Adapter(adaptee)  
  20.     adapter.Request() 

十四、备忘录模式

模式特点:在不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,以后可以将对象恢复到这个状态。

程序实例:将Originator对象的状态封装成Memo对象保存在Caretaker内

代码特点:无

  1. 备忘录模式   
  2.  
  3. class Originator:  
  4.     def __init__(self):  
  5.         self.state = ""  
  6.     def Show(self):  
  7.         print self.state  
  8.     def CreateMemo(self):  
  9.         return Memo(self.state)  
  10.     def SetMemo(self,memo):  
  11.         self.state = memo.state  
  12.  
  13. class Memo:  
  14.     state= ""  
  15.     def __init__(self,ts):  
  16.         self.state = ts  
  17.  
  18. class Caretaker:  
  19.     memo = ""  
  20.  
  21. if __name__ == "__main__":  
  22.     on = Originator()  
  23.     on.state = "on" 
  24.     on.Show()  
  25.     c = Caretaker()  
  26.     c.memo=on.CreateMemo()  
  27.     on.state="off" 
  28.     on.Show()  
  29.     on.SetMemo(c.memo)  
  30.     on.Show() 

十五、组合模式

模式特点:将对象组合成成树形结构以表示“部分-整体”的层次结构

程序实例:公司人员的组织结构

代码特点:无

  1. 组合模式   
  2.  
  3. class Component:  
  4.     def __init__(self,strName):  
  5.         self.m_strName = strName  
  6.     def Add(self,com):  
  7.         pass 
  8.     def Display(self,nDepth):  
  9.         pass 
  10.  
  11. class Leaf(Component):  
  12.     def Add(self,com):  
  13.         print "leaf can't add" 
  14.     def Display(self,nDepth):  
  15.         strtemp = ""  
  16.         for i in range(nDepth):  
  17.             strtemp=strtemp+"-" 
  18.         strtemp=strtemp+self.m_strName  
  19.         print strtemp  
  20.  
  21. class Composite(Component):  
  22.     def __init__(self,strName):  
  23.         self.m_strName = strName  
  24.         self.c = []  
  25.     def Add(self,com):  
  26.         self.c.append(com)  
  27.     def Display(self,nDepth):  
  28.         strtemp=""  
  29.         for i in range(nDepth):  
  30.             strtemp=strtemp+"-" 
  31.         strtemp=strtemp+self.m_strName  
  32.         print strtemp  
  33.         for com in self.c:  
  34.             com.Display(nDepth+2)  
  35.  
  36. if __name__ == "__main__":  
  37.     p = Composite("Wong")  
  38.     p.Add(Leaf("Lee"))  
  39.     p.Add(Leaf("Zhao"))  
  40.     p1 = Composite("Wu")  
  41.     p1.Add(Leaf("San"))  
  42.     p.Add(p1)  
  43.     p.Display(1); 

#p#

十六、迭代器模式

模式特点:提供方法顺序访问一个聚合对象中各元素,而又不暴露该对象的内部表示

说明:这个模式没有写代码实现,原因是使用Python的列表和for ... in list就能够完成不同类型对象聚合的迭代功能了。

十七、单例模式

模式特点:保证类仅有一个实例,并提供一个访问它的全局访问点。

说明:为了实现单例模式费了不少工夫,后来查到一篇博文对此有很详细的介绍,而且实现方式也很丰富,通过对代码的学习可以了解更多Python的用法。以下的代码出自GhostFromHeaven的专栏,地址:http://blog.csdn.net/ghostfromheaven/article/details/7671853。不过正如其作者在Python单例模式***版所说:

我要问的是,Python真的需要单例模式吗?我指像其他编程语言中的单例模式。

答案是:不需要!

因为,Python有模块(module),最pythonic的单例典范。

模块在在一个应用程序中只有一份,它本身就是单例的,将你所需要的属性和方法,直接暴露在模块中变成模块的全局变量和方法即可!

  1. 单例模式(四种方法)   
  2.  
  3. #-*- encoding=utf-8 -*-  
  4. print '----------------------方法1--------------------------' 
  5. #方法1,实现__new__方法  
  6. #并在将一个类的实例绑定到类变量_instance上,  
  7. #如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回  
  8. #如果cls._instance不为None,直接返回cls._instance  
  9. class Singleton(object):  
  10.     def __new__(cls, *args, **kw):  
  11.         if not hasattr(cls'_instance'):  
  12.             orig = super(Singleton, cls)  
  13.             cls._instance = orig.__new__(cls, *args, **kw)  
  14.         return cls._instance  
  15.  
  16. class MyClass(Singleton):  
  17.     a = 1 
  18.  
  19. one = MyClass()  
  20. two = MyClass()  
  21.  
  22. two.a = 3 
  23. print one.a  
  24. #3  
  25. #one和two完全相同,可以用id(), ==, is检测  
  26. print id(one)  
  27. #29097904  
  28. print id(two)  
  29. #29097904  
  30. print one == two  
  31. #True  
  32. print one is two  
  33. #True  
  34.  
  35. print '----------------------方法2--------------------------' 
  36. #方法2,共享属性;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)  
  37. #同一个类的所有实例天然拥有相同的行为(方法),  
  38. #只需要保证同一个类的所有实例具有相同的状态(属性)即可  
  39. #所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict)  
  40. #可参看:http://code.activestate.com/recipes/66531/  
  41. class Borg(object):  
  42.     _state = {}  
  43.     def __new__(cls, *args, **kw):  
  44.         ob = super(Borg, cls).__new__(cls, *args, **kw)  
  45.         ob.__dict__ = cls._state  
  46.         return ob  
  47.  
  48. class MyClass2(Borg):  
  49.     a = 1 
  50.  
  51. one = MyClass2()  
  52. two = MyClass2()  
  53.  
  54. #one和two是两个不同的对象,id, ==, is对比结果可看出  
  55. two.a = 3 
  56. print one.a  
  57. #3  
  58. print id(one)  
  59. #28873680  
  60. print id(two)  
  61. #28873712  
  62. print one == two  
  63. #False  
  64. print one is two  
  65. #False  
  66. #但是one和two具有相同的(同一个__dict__属性),见:  
  67. print id(one.__dict__)  
  68. #30104000  
  69. print id(two.__dict__)  
  70. #30104000  
  71.  
  72. print '----------------------方法3--------------------------' 
  73. #方法3:本质上是方法1的升级(或者说高级)版  
  74. #使用__metaclass__(元类)的高级python用法  
  75. class Singleton2(type):  
  76.     def __init__(cls, name, bases, dict):  
  77.         super(Singleton2, cls).__init__(name, bases, dict)  
  78.         cls._instance = None 
  79.     def __call__(cls, *args, **kw):  
  80.         if cls._instance is None:  
  81.             cls._instance = super(Singleton2, cls).__call__(*args, **kw)  
  82.         return cls._instance  
  83.  
  84. class MyClass3(object):  
  85.     __metaclass__ = Singleton2  
  86.  
  87. one = MyClass3()  
  88. two = MyClass3()  
  89.  
  90. two.a = 3 
  91. print one.a  
  92. #3  
  93. print id(one)  
  94. #31495472  
  95. print id(two)  
  96. #31495472  
  97. print one == two  
  98. #True  
  99. print one is two  
  100. #True  
  101.  
  102. print '----------------------方法4--------------------------' 
  103. #方法4:也是方法1的升级(高级)版本,  
  104. #使用装饰器(decorator),  
  105. #这是一种更pythonic,更elegant的方法,  
  106. #单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的  
  107. def singleton(cls, *args, **kw):  
  108.     instances = {}  
  109.     def _singleton():  
  110.         if cls not in instances:  
  111.             instances[cls] = cls(*args, **kw)  
  112.         return instances[cls]  
  113.     return _singleton  
  114.  
  115. @singleton 
  116. class MyClass4(object):  
  117.     a = 1 
  118.     def __init__(self, x=0):  
  119.         self.x = x  
  120.  
  121. one = MyClass4()  
  122. two = MyClass4()  
  123.  
  124. two.a = 3 
  125. print one.a  
  126. #3  
  127. print id(one)  
  128. #29660784  
  129. print id(two)  
  130. #29660784  
  131. print one == two  
  132. #True  
  133. print one is two  
  134. #True  
  135. one.x = 1 
  136. print one.x  
  137. #1  
  138. print two.x  
  139. #1 

十八、桥接模式

模式特点:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

程序实例:两种品牌的手机,要求它们都可以运行游戏和通讯录两个软件,而不是为每个品牌的手机都独立编写不同的软件。

代码特点:虽然使用了object的新型类,不过在这里不是必须的,是对在Python2.2之后“尽量使用新型类”的建议的遵从示范。

  1. 桥接模式   
  2.  
  3. class HandsetSoft(object):  
  4.     def Run(self):  
  5.         pass 
  6.  
  7. class HandsetGame(HandsetSoft):  
  8.     def Run(self):  
  9.         print "Game" 
  10.  
  11. class HandsetAddressList(HandsetSoft):  
  12.     def Run(self):  
  13.         print "Address List" 
  14.  
  15. class HandsetBrand(object):  
  16.     def __init__(self):  
  17.         self.m_soft = None 
  18.     def SetHandsetSoft(self,temp):  
  19.         self.m_soft= temp  
  20.     def Run(self):  
  21.         pass 
  22.  
  23. class HandsetBrandM(HandsetBrand):  
  24.     def Run(self):  
  25.         if not (self.m_soft == None):  
  26.             print "BrandM" 
  27.             self.m_soft.Run()  
  28.  
  29. class HandsetBrandN(HandsetBrand):  
  30.     def Run(self):  
  31.         if not (self.m_soft == None):  
  32.             print "BrandN" 
  33.             self.m_soft.Run()  
  34.  
  35. if __name__ == "__main__":  
  36.     brand = HandsetBrandM()  
  37.     brand.SetHandsetSoft(HandsetGame())  
  38.     brand.Run()  
  39.     brand.SetHandsetSoft(HandsetAddressList())  
  40.     brand.Run() 

十九、命令模式

模式特点:将请求封装成对象,从而使可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

程序实例:烧烤店有两种食物,羊肉串和鸡翅。客户向服务员点单,服务员将点好的单告诉大厨,由大厨进行烹饪。

代码特点:注意在遍历列表时不要用注释的方式删除,否则会出现bug。bug示例程序附在后面,我认为这是因为remove打乱了for迭代查询列表的顺序导致的。

  1. 命令模式   
  2.  
  3. class Barbucer:  
  4.     def MakeMutton(self):  
  5.         print "Mutton" 
  6.     def MakeChickenWing(self):  
  7.         print "Chicken Wing" 
  8.  
  9. class Command:  
  10.     def __init__(self,temp):  
  11.         self.receiver=temp  
  12.     def ExecuteCmd(self):  
  13.         pass 
  14.  
  15. class BakeMuttonCmd(Command):  
  16.     def ExecuteCmd(self):  
  17.         self.receiver.MakeMutton()  
  18.  
  19. class ChickenWingCmd(Command):  
  20.     def ExecuteCmd(self):  
  21.         self.receiver.MakeChickenWing()  
  22.  
  23. class Waiter:  
  24.     def __init__(self):  
  25.         self.order =[]  
  26.     def SetCmd(self,command):  
  27.         self.order.append(command)  
  28.         print "Add Order" 
  29.     def Notify(self):  
  30.         for cmd in self.order:  
  31.             #self.order.remove(cmd)  
  32.             #lead to a bug  
  33.             cmd.ExecuteCmd()  
  34.               
  35.  
  36. if __name__ == "__main__":  
  37.     barbucer=Barbucer()  
  38.     cmd=BakeMuttonCmd(barbucer)  
  39.     cmd2=ChickenWingCmd(barbucer)  
  40.     girl=Waiter()  
  41.     girl.SetCmd(cmd)  
  42.     girl.SetCmd(cmd2)  
  43.     girl.Notify() 

在for中remove会导致bug的展示代码:

  1. bug   
  2.  
  3. c=[0,1,2,3]  
  4. for i in c:  
  5.     print i  
  6.     c.remove(i)  
  7.  
  8. #output:  
  9. #0  
  10. #2 

二十、职责链模式

模式特点:使多个对象都有机会处理请求,从而避免发送者和接收者的耦合关系。将对象连成链并沿着这条链传递请求直到被处理。

程序实例:请假和加薪等请求发给上级,如果上级无权决定,那么递交给上级的上级。

代码特点:无

  1. 职责链模式   
  2.  
  3. class Request:  
  4.     def __init__(self,tcontent,tnum):  
  5.         self.content = tcontent  
  6.         self.num = tnum  
  7.  
  8. class Manager:  
  9.     def __init__(self,temp):  
  10.         self.name = temp  
  11.     def SetSuccessor(self,temp):  
  12.         self.manager = temp  
  13.     def GetRequest(self,req):  
  14.         pass 
  15.  
  16. class CommonManager(Manager):  
  17.     def GetRequest(self,req):  
  18.         if(req.num>=0 and req.num<10):  
  19.             print "%s handled %d request." %(self.name,req.num)  
  20.         else:  
  21.             self.manager.GetRequest(req)  
  22.  
  23. class MajorDomo(Manager):  
  24.     def GetRequest(self,req):  
  25.         if(req.num>=10):  
  26.             print "%s handled %d request." %(self.name,req.num)  
  27.  
  28. if __name__ == "__main__":  
  29.     common = CommonManager("Zhang")  
  30.     major = MajorDomo("Lee")  
  31.     common.SetSuccessor(major)  
  32.     req = Request("rest",33)  
  33.     common.GetRequest(req)  
  34.     req2 = Request("salary",3)  
  35.     common.GetRequest(req2) 

#p#

二十一、中介者模式

模式特点:用一个对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互。

程序实例:两个对象通过中介者相互通信

代码特点:无

  1. 中介者模式   
  2.  
  3. class Mediator:  
  4.     def Send(self,message,col):  
  5.         pass 
  6.  
  7. class Colleague:  
  8.     def __init__(self,temp):  
  9.         self.mediator = temp  
  10.  
  11. class Colleague1(Colleague):  
  12.     def Send(self,message):  
  13.         self.mediator.Send(message,self)  
  14.     def Notify(self,message):  
  15.         print "Colleague1 get a message:%s" %message  
  16.  
  17. class Colleague2(Colleague):  
  18.     def Send(self,message):  
  19.         self.mediator.Send(message,self)  
  20.     def Notify(self,message):  
  21.         print "Colleague2 get a message:%s" %message  
  22.  
  23. class ConcreteMediator(Mediator):  
  24.     def Send(self,message,col):  
  25.         if(col==col1):  
  26.             col2.Notify(message)  
  27.         else:  
  28.             col1.Notify(message)  
  29.  
  30. if __name__ == "__main__":  
  31.     m =ConcreteMediator()  
  32.     col1 = Colleague1(m)  
  33.     col2 = Colleague1(m)  
  34.     m.col1=col1  
  35.     m.col2=col2  
  36.     col1.Send("How are you?");  
  37.     col2.Send("Fine."); 

二十二、享元模式

模式特点:运用共享技术有效地支持大量细粒度的对象。

程序实例:一个网站工厂,根据用户请求的类别返回相应类别的网站。如果这种类别的网站已经在服务器上,那么返回这种网站并加上不同用户的独特的数据;如果没有,那么生成一个。

代码特点:为了展示每种网站的由用户请求的次数,这里为它们建立了一个引用次数的字典。

之所以不用Python的sys模块中的sys.getrefcount()方法统计引用计数是因为有的对象可能在别处被隐式的引用,从而增加了引用计数。 

  1. 享元模式   
  2.  
  3. import sys  
  4.  
  5. class WebSite:  
  6.     def Use(self):  
  7.         pass 
  8.  
  9. class ConcreteWebSite(WebSite):  
  10.     def __init__(self,strName):  
  11.         self.name = strName  
  12.     def Use(self,user):  
  13.         print "Website type:%s,user:%s" %(self.name,user)  
  14.  
  15. class UnShareWebSite(WebSite):  
  16.     def __init__(self,strName):  
  17.         self.name = strName  
  18.     def Use(self,user):  
  19.         print "UnShare Website type:%s,user:%s" %(self.name, user)  
  20.  
  21. class WebFactory:  
  22.     def __init__(self):  
  23.         test = ConcreteWebSite("test")  
  24.         self.webtype ={"test":test}  
  25.         self.count = {"test":0}  
  26.     def GetWeb(self,webtype):  
  27.         if webtype not in self.webtype:  
  28.             temp = ConcreteWebSite(webtype)  
  29.             self.webtype[webtype] = temp  
  30.             self.count[webtype] =1 
  31.         else:  
  32.             temp = self.webtype[webtype]  
  33.             self.count[webtype] = self.count[webtype]+1 
  34.         return temp  
  35.     def GetCount(self):  
  36.         for key in self.webtype:  
  37.             #print "type: %s, count:%d" %(key,sys.getrefcount(self.webtype[key]))  
  38.             print "type: %s, count:%d " %(key,self.count[key])  
  39.  
  40. if __name__ == "__main__":  
  41.     f = WebFactory()  
  42.     ws=f.GetWeb("blog")  
  43.     ws.Use("Lee")  
  44.     ws2=f.GetWeb("show")  
  45.     ws2.Use("Jack")  
  46.     ws3=f.GetWeb("blog")  
  47.     ws3.Use("Chen")  
  48.     ws4=UnShareWebSite("TEST")  
  49.     ws4.Use("Mr.Q")  
  50.     print f.webtype  
  51.     f.GetCount() 

二十三、解释器模式

模式特点:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

程序实例:(只是模式特点的最简单示范)

代码特点:无

  1. 解释器模式   
  2.  
  3. class Context:  
  4.     def __init__(self):  
  5.         self.input=""  
  6.         self.output=""  
  7.  
  8. class AbstractExpression:  
  9.     def Interpret(self,context):  
  10.         pass 
  11.  
  12. class Expression(AbstractExpression):  
  13.     def Interpret(self,context):  
  14.         print "terminal interpret" 
  15.  
  16. class NonterminalExpression(AbstractExpression):  
  17.     def Interpret(self,context):  
  18.         print "Nonterminal interpret" 
  19.  
  20. if __name__ == "__main__":  
  21.     context= ""  
  22.     c = []  
  23.     c = c + [Expression()]  
  24.     c = c + [NonterminalExpression()]  
  25.     c = c + [Expression()]  
  26.     c = c + [Expression()]  
  27.     for a in c:  
  28.         a.Interpret(context) 

二十四、访问者模式

模式特点:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

程序实例:对于男人和女人(接受访问者的元素,ObjectStructure用于穷举这些元素),不同的遭遇(具体的访问者)引发两种对象的不同行为。

代码特点:无

  1. 访问者模式   
  2.  
  3. # -*- coding: UTF-8 -*-  
  4. class Person:  
  5.     def Accept(self,visitor):  
  6.         pass 
  7.  
  8. class Man(Person):  
  9.     def Accept(self,visitor):  
  10.         visitor.GetManConclusion(self)  
  11.  
  12. class Woman(Person):  
  13.     def Accept(self,visitor):  
  14.         visitor.GetWomanConclusion(self)  
  15.  
  16. class Action:  
  17.     def GetManConclusion(self,concreteElementA):  
  18.         pass 
  19.     def GetWomanConclusion(self,concreteElementB):  
  20.         pass 
  21.  
  22. class Success(Action):  
  23.     def GetManConclusion(self,concreteElementA):  
  24.         print "男人成功时,背后有个伟大的女人" 
  25.     def GetWomanConclusion(self,concreteElementB):  
  26.         print "女人成功时,背后有个不成功的男人" 
  27.  
  28. class Failure(Action):  
  29.     def GetManConclusion(self,concreteElementA):  
  30.         print "男人失败时,闷头喝酒,谁也不用劝" 
  31.     def GetWomanConclusion(self,concreteElementB):  
  32.         print "女人失败时,眼泪汪汪,谁也劝不了" 
  33.  
  34.  
  35. class ObjectStructure:  
  36.     def __init__(self):  
  37.         self.plist=[]  
  38.     def Add(self,p):  
  39.         self.plist=self.plist+[p]  
  40.     def Display(self,act):  
  41.         for p in self.plist:  
  42.             p.Accept(act)  
  43.  
  44. if __name__ == "__main__":  
  45.     os = ObjectStructure()  
  46.     os.Add(Man())  
  47.     os.Add(Woman())  
  48.     sc = Success()  
  49.     os.Display(sc)  
  50.     fl = Failure()  
  51.     os.Display(fl) 

原文链接:http://www.cnblogs.com/wuyuegb2312/archive/2013/04/09/3008320.html

责任编辑:张伟 来源: 博客园
相关推荐

2011-12-19 14:28:14

2013-11-26 15:44:25

2024-02-23 08:57:42

Python设计模式编程语言

2012-02-17 15:49:11

技术沙龙

2023-12-12 11:09:55

模板方法模式python设计模式

2011-09-14 10:29:23

Android UI设

2012-03-05 15:19:12

PHP

2012-03-06 13:32:59

PHP

2010-08-11 09:15:07

设计模式Python

2023-12-13 13:28:16

装饰器模式Python设计模式

2021-04-23 14:14:46

设计模式对象

2012-03-05 16:23:26

技术沙龙

2020-03-31 21:50:41

JavaScript前端技术

2010-10-09 09:25:35

Python工厂模式

2023-03-27 00:20:48

2012-01-18 10:47:38

ibmdw

2022-05-27 11:33:02

前端代码设计模式

2021-08-19 15:19:16

代码开发模型

2019-03-11 08:36:11

Python代码Flask

2012-03-06 16:29:24

开发技术周刊
点赞
收藏

51CTO技术栈公众号