做者:五嶽
出處:http://www.cnblogs.com/wuyuegb2312 python
上一週把《大話設計模式》看完了,對面向對象技術有了新的理解,對於一個在C下寫代碼比較多、偶爾會用到一些腳本語言寫腳本的人來講,非常開闊眼界。《大話設計模式》的代碼使用C#寫成的,而在本人接觸到的面嚮對象語言中,只對C++和Python還算了解,爲了加深對各個模式的理解,我在網上下載了一個C++版的源代碼,並根據本身的理解邊讀這本書邊動手實踐C++源代碼,同時將其改寫成了Python代碼,算是一箭三雕吧。程序員
因爲這些代碼的目的是展現各個設計模式而非完成一個具體的複雜任務,基於C++版本改寫,例子的取材也和《大話設計模式》基本相同,再加上我的水平有限,所以這些Python版代碼寫的比較簡單,雖然能跑起來是不假,不過不免有bug,並且實現也不必定最優,C++的味道比較濃而不夠pythonic,還請高手包容指正。不過我仍是儘可能把或多或少有些pythonic的東西放在每一個模式的「代碼特色」部分進行展現,而這個「代碼特色」裏也不只僅是pythonic的東西。web
使用Python版本爲2.6。算法
配圖一樣摘自《大話設計模式》,所以是C#風格的UML類圖,爲了便於排版已經縮小了。數據庫
1、簡單工廠模式編程
模式特色:工廠根據條件產生不一樣功能的類。設計模式
程序實例:四則運算計算器,根據用戶的輸入產生相應的運算類,用這個運算類處理具體的運算。服務器
代碼特色:C/C++中的switch...case...分支使用字典的方式代替。app
使用異常機制對除數爲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()
2、策略模式
模式特色:定義算法家族而且分別封裝,它們之間能夠相互替換而不影響客戶端。
程序實例:商場收銀軟件,須要根據不一樣的銷售策略方式進行收費
代碼特色:不一樣於同例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))
3、裝飾模式
模式特色:動態地爲對象增長額外的職責
程序實例:展現一我的一件一件穿衣服的過程。
代碼特色:無
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()
4、代理模式
模式特色:爲其餘對象提供一種代理以控制對這個對象的訪問。
程序實例:同模式特色描述。
代碼特色:無
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()
5、工廠方法模式
模式特色:定義一個用於建立對象的接口,讓子類決定實例化哪個類。這使得一個類的實例化延遲到其子類。
程序實例:基類雷鋒類,派生出學生類和志願者類,由這兩種子類完成「學雷鋒」工做。子類的建立由雷鋒工廠的對應的子類完成。
代碼特色:無
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()
6、原型模式
模式特色:用原型實例指定建立對象的種類,而且經過拷貝這些原型建立新的對象。
程序實例:從簡歷原型,生成新的簡歷
代碼特色:簡歷類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()
7、模板方法模式
模式特色:定義一個操做中的算法骨架,將一些步驟延遲至子類中。
程序實例:考試時使用同一種考卷(父類),不一樣學生上交本身填寫的試卷(子類方法的實現)
代碼特色:無
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()
8、外觀模式
模式特色:爲一組調用提供一致的接口。
程序實例:接口將幾種調用分別組合成爲兩組,用戶經過接口調用其中的一組。
代碼特色:無
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()
9、建造者模式
模式特色:將一個複雜對象的構建(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()
10、觀察者模式
模式特色:定義了一種一對多的關係,讓多個觀察對象同時監聽一個主題對象,當主題對象狀態發生變化時會通知全部觀察者。
程序實例:公司裏有兩種上班時趁老闆不在時偷懶的員工:看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()
11、抽象工廠模式
模式特色:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們的類。
程序實例:提供對不一樣的數據庫訪問的支持。
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()
12、狀態模式
模式特色:當一個對象的內在狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。
程序實例:描述一個程序員的工做狀態,當須要改變狀態時發生改變,不一樣狀態下的方法實現不一樣
代碼特色:無
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()
十3、適配器模式
模式特色:將一個類的接口轉換成爲客戶但願的另一個接口。
程序實例:用戶經過適配器使用一個類的方法。
代碼特色:無
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()
十4、備忘錄模式
模式特色:在不破壞封裝性的前提下捕獲一個對象的內部狀態,並在該對象以外保存這個狀態,之後能夠將對象恢復到這個狀態。
程序實例:將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()
十5、組合模式
模式特色:將對象組合成成樹形結構以表示「部分-總體」的層次結構
程序實例:公司人員的組織結構
代碼特色:無
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);
十6、迭代器模式
模式特色:提供方法順序訪問一個聚合對象中各元素,而又不暴露該對象的內部表示
說明:這個模式沒有寫代碼實現,緣由是使用Python的列表和for ... in list就可以完成不一樣類型對象聚合的迭代功能了。
十7、單例模式
模式特色:保證類僅有一個實例,並提供一個訪問它的全局訪問點。
說明: 爲了實現單例模式費了很多工夫,後來查到一篇博文對此有很詳細的介紹,並且實現方式也很豐富,經過對代碼的學習能夠了解更多Python的用法。如下的代碼出自GhostFromHeaven的專欄,地址:http://blog.csdn.net/ghostfromheaven/article/details/7671853。不過正如其做者在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
十8、橋接模式
模式特色:將抽象部分與它的實現部分分離,使它們均可以獨立地變化。
程序實例:兩種品牌的手機,要求它們均可以運行遊戲和通信錄兩個軟件,而不是爲每一個品牌的手機都獨立編寫不一樣的軟件。
代碼特色:雖然使用了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()
十9、命令模式
模式特色:將請求封裝成對象,從而使可用不一樣的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤消的操做。
程序實例:燒烤店有兩種食物,羊肉串和雞翅。客戶向服務員點單,服務員將點好的單告訴大廚,由大廚進行烹飪。
代碼特色:注意在遍歷列表時不要用註釋的方式刪除,不然會出現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()
在for中remove會致使bug的展現代碼:
c=[0,1,2,3] for i in c: print i c.remove(i) #output: #0 #2
二10、職責鏈模式
模式特色:使多個對象都有機會處理請求,從而避免發送者和接收者的耦合關係。將對象連成鏈並沿着這條鏈傳遞請求直到被處理。
程序實例:請假和加薪等請求發給上級,若是上級無權決定,那麼遞交給上級的上級。
代碼特色:無
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)
二11、中介者模式
模式特色:用一個對象來封裝一系列的對象交互,中介者使各對象不須要顯示地相互引用,從而使耦合鬆散,並且能夠獨立地改變它們之間的交互。
程序實例:兩個對象經過中介者相互通訊
代碼特色:無
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.");
二12、享元模式
模式特色:運用共享技術有效地支持大量細粒度的對象。
程序實例:一個網站工廠,根據用戶請求的類別返回相應類別的網站。若是這種類別的網站已經在服務器上,那麼返回這種網站並加上不一樣用戶的獨特的數據;若是沒有,那麼生成一個。
代碼特色:爲了展現每種網站的由用戶請求的次數,這裏爲它們創建了一個引用次數的字典。
之因此不用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()
二十3、解釋器模式
模式特色:給定一個語言,定義它的文法的一種表示,並定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。
程序實例:(只是模式特色的最簡單示範)
代碼特色:無
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)
二十4、訪問者模式
模式特色:表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下定義做用於這些元素的新操做。
程序實例:對於男人和女人(接受訪問者的元素,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)