python实践设计模式(二)Builder,Singleton,Prototype
学习python有一段时间,之前就是看看书,最后发现只有实践才能真正学到东西,只有在解决问题中才能真正掌握。之前大牛也有用python实现各种设计模式的,我自己参考之前在学习用C#实现设计模式的经历,也想把23种模式逐一实践,从网上查了一些资料,才明白python虽然是面向对象的,但是和C#,java语言不太一样。影响设计方法不一样有以下几点:
1.python没有接口Interface的类型。
2.由于《Design Patterns—Elements of Reusable Object-Oriented Software》一书采用的是C++来讲述设计模式,因此访问控制符(public、protected和private等关键字)和静态成员方法(类方法)等都可以直接使用,但是这些特性在Python中都无法用到,原因是Python采了与C++完全不同的对象模式。
3.python不是强类型,弱化了多态的概念,一个对象很少只是一个类的实例,而是可以在运行时动态改变,支持相同请求的不同对象针对同一请求所触发的操作可能完全不同。
4.python代码生存在modules中而不必须在class中。
5.python有一些特殊语法运用了设计模式(如decorator ),可以直接应用。
有了以上的不同,就注定python在运用设计模式上与其他面向对象语言的不同,下面是我尝试的实现。
《Design Patterns》一书把设计模式分为了3大类,创建型模式(creational pattern)、结构型模式(structural pattern)和行为型模式(behavioral patterns)。
一. 创建型模式(creational pattern)
对类的实例化过程进行了抽象,能够使软件模块做到与对象创建和组织的无关性。为了使体系结构更加清晰,一些软件在设计上要求当创建类的具体实例时,能够根据具体的语境来动态地决定怎样创建对象,创建哪些对象,以及怎样组织和表示这些对象,而创建型模式所要描述的就是该如何来解决这些问题。
创建型模式包括以下几种:
Simple Factory模式
专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。
Factory Method模式
将对象的创建交由父类中定义的一个标准方法来完成,而不是其构造函数,究竟应该创建何种对象由具体的子类负责决定。
Abstract Factory模式
提供一个共同的接口来创建相互关联的多个对象。
Singleton模式
保证系统只会产生该类的一个实例,同时还负责向外界提供访问该实例的标准方法。
Builder模式
将复杂对象的创建同它们的具体表现形式(representation)区别开来,这样可以根据需要得到具有不同表现形式的对象。
Prototype模式
利用一个能对自身进行复制的类,使得对象的动态创建变得更加容易。
本次先实践Simple Factory模式,Factory Method模式和 Abstract Factory模式,其他模式后续会涉及。
1.Simple Factory模式
Simple Factory模式不是独立的设计模式,他是Factory Method模式的一种简单的、特殊的实现。他也被称为静态工厂模式,通常创建者的创建方法被设计为static方便调用,但是python没有static一说。所以可以把创建者也就是工厂设计为一个普通class或全局函数即可。如果是class还需要实例化才能调用工厂方法,而全局函数比较简单,比较接近静态工厂的简便特性。
Simple Factory模式包含以下角色部分,UML可参考下图:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。由一个具体类实现,通常该类的工厂方法是静态的。在python中工厂为一个普通class或全局函数。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。在python中抽象产品一般为父类。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。由一个具体类实现。
一个Simple Factory模式代码实例
1 class car: 2 '''interface as Product''' 3 def drive(self): 4 pass 5 6 class BMW(car): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the BMW as "+self.__name 12 13 class Benz(car): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the Benz as "+self.__name 19 20 class driver: 21 '''Factory also called Creator''' 22 def driverCar(self,name): 23 if name=="BMW": 24 return BMW("BMW") 25 elif name=="Benz": 26 return Benz("Benz") 27 else: 28 raise MyInputException(name) 29 30 class MyInputException(Exception): 31 def __init__(self, name): 32 Exception.__init__(self) 33 self.name = name 34 35 36 if __name__ == "__main__": 37 print "please input \"BMW\" or \"Benz\" :" 38 carname=raw_input() 39 dier=driver() 40 try: 41 d=dier.driverCar(carname) 42 except MyInputException,e: 43 print "input worry name "+e.name 44 else: 45 d.drive()
用全局函数改写工厂类,其他部分省略,变化部分如下:
1 '''Factory also called Creator''' 2 def driver(name): 3 if name=="BMW": 4 return BMW("BMW") 5 elif name=="Benz": 6 return Benz("Benz") 7 else: 8 raise MyInputException(name) 9 10 if __name__ == "__main__": 11 print "please input \"BMW\" or \"Benz\" :" 12 carname=raw_input() 13 try: 14 d=driver(carname) 15 except MyInputException,e: 16 print "input worry name "+e.name 17 else: 18 d.drive()
2. Factory Method工厂模式
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。对于python来说,就是工厂类被具体工厂继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。也就是工厂外面再封装一层。
1) 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
2) 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3) 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在python中抽象产品一般为父类。
4) 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。由一个具体类实现。
一个Factory Method代码实例
1 class car: 2 '''interface as Product''' 3 def drive(self): 4 pass 5 6 class BMW(car): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the BMW as "+self.__name 12 13 class Benz(car): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the Benz as "+self.__name 19 20 class driver: 21 '''Factory also called Creator''' 22 def driverCar(self): 23 return car() 24 25 class BMWdriver(driver): 26 '''Concrete Creator''' 27 def driverCar(self): 28 return BMW("BMW") 29 30 class Benzdriver(driver): 31 '''Concrete Creator''' 32 def driverCar(self): 33 return Benz("Benz") 34 35 if __name__ == "__main__": 36 driver=BMWdriver() 37 car=driver.driverCar() 38 car.drive() 39 driver=Benzdriver() 40 car=driver.driverCar() 41 car.drive()
3. Abstract Factory模式
抽象工厂是工厂模式的进一步延伸,产品的类变的更加复杂,也就说产品不只是一个接口或父类而是有多个接口和父类了,形成了一个产品族的概念。模式的角色与Factory Method基本一样,UML图如下:
抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。 不过使用抽象工厂是有条件的:
1.系统中有多个产品族,而系统一次只可能消费其中一族产品
2.同属于同一个产品族的产品在一起使用,这一约束必须在系统的设计中体现出来。
简单的实现代码如下:
1 class Newcar: 2 '''Abstract Product''' 3 def drive(self): 4 pass 5 6 class NewBMW(Newcar): 7 '''Concrete Product''' 8 def __init__(self,carname): 9 self.__name=carname 10 def drive(self): 11 print "Drive the New BMW as "+self.__name 12 13 class NewBenz(Newcar): 14 '''Concrete Product''' 15 def __init__(self,carname): 16 self.__name=carname 17 def drive(self): 18 print "Drive the New Benz as "+self.__name 19 20 class Oldcar: 21 '''Abstract Product''' 22 def drive(self): 23 pass 24 25 class OldBMW(Oldcar): 26 '''Concrete Product''' 27 def __init__(self,carname): 28 self.__name=carname 29 def drive(self): 30 print "Drive the Old BMW as "+self.__name 31 32 class OldBenz(Oldcar): 33 '''Concrete Product''' 34 def __init__(self,carname): 35 self.__name=carname 36 def drive(self): 37 print "Drive the Old Benz as "+self.__name 38 39 class driver: 40 '''Abstract Factory also called Creator''' 41 def driverNewCar(self): 42 return Newcar() 43 def driverOldCar(self): 44 return Oldcar() 45 46 class BMWdriver(driver): 47 '''Concrete Factory or Creator''' 48 def driverNewCar(self): 49 return NewBMW("NewBMW") 50 def driverOldCar(self): 51 return OldBMW("OldBMW") 52 53 class Benzdriver(driver): 54 '''Concrete Factory or Creator''' 55 def driverNewCar(self): 56 return NewBenz("NewBenz") 57 def driverOldCar(self): 58 return OldBenz("OldBenz") 59 60 if __name__ == "__main__": 61 driver=BMWdriver() 62 car=driver.driverNewCar() 63 car.drive() 64 car=driver.driverOldCar() 65 car.drive() 66 driver=Benzdriver() 67 car=driver.driverNewCar() 68 car.drive() 69 car=driver.driverOldCar() 70 car.drive()
未完待续……