將对象的创建可独立於某定制类來進行,客户端无需了解创建对象如何被创建,只需知道要传递的接口、方法、参数就能够创建所需类型的对象,日後可轻松地在工厂中再添加其它类型以创建对象,而无需更改客户端代码。
工广模式主要分类:
- 简单工厂模式:定義統一工广並提供訪問接口,並對傳入參數進行需求對象之创建,此式通常用於一次创建單一實例之場合中。
- 工厂方法模式:定義抽象工广並提供共用訪問接口並讓其繼承具体子類來負責创建需求對象之實例,此模式通常用於一次创建多個實例之場合中。
- 抽象工厂模式:主要由各專門工广具体类來创建其某特定類型之对象,此模式通常用於创建某一專門類型實例之場合中。
二、简单工厂模式
UML图
示例:
# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod
class Animal(metaclass = ABCMeta): #动物抽象类
@abstractmethod
def do_say(self):
raise ImplementedError
class Dog(Animal): #具体子类1:狗類
def do_say(self):
print("Bhow Bhow!!")
class Cat(Animal): #具体子类2:猫类
def do_say(self):
print("Meow Meow!!")
class SimpleFactory(object): #簡單工广
def make_sound(self, object_type):
return eval(object_type)().do_say()
#實際業務邏輯場景
if __name__ == '__main__':
sf =SimpleFactory()
animal = input("Which animal should make_sound Dog or Cat?")
sf.make_sound(animal)
輸出:
Which animal should make_sound Dog or Cat?Cat
Meow Meow!!
上述代码中SimpleFactory就是簡單工厂模式,當我们输入Cat或Dog就会通过它來调用类中定義之make_sound()方法,而eval()方法可将字符串直接轉型為有效的表达式,如果此处不用eval()方法也可以采用if elif else 形式來对傳入參數作比對判定,但採用eval()方式显然更加优雅。
工厂方法模式
提供共同接口但讓繼承子類負責去创建其專門類之實例。
UML图
示例:
# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod
class Animal(metaclass=ABCMeta): #抽象动物类
@abstractmethod
def do_say(self):
raise ImplementedError
class Dog(Animal): #具体子类1:狗类
def do_say(self):
print("Bhow Bhow!!")
class Cat(Animal): #具体子类2:猫类
def do_say(self):
print("Meow Meow!!")
class AbstractMethod(metaclass=ABCMeta): #工厂方法抽象类:負責提供共用接口
def __init__(self):
self.sets = []
self.createObject()
@abstractmethod
def createObject(self):
raise ImplementedError
def getSets(self):
return self.sets
def addSets(self, object):
self.sets.append(object)
class AbstractMethodConcrete(AbstractMethod): #抽象方法具体类
def createObject(self):
self.addSets(Dog())
self.addSets(Cat())
if __name__ == '__main__':
amc = AbstractMethodConcrete()
print("Creating animals..", type(amc).__name__)
print("Animal has sets --", amc.getSets())
[obj.do_say() for obj in amc.Sets]
輸出:
Creating animals.. AbstractMethodConcrete
Animal has sets -- [<__main__.Dog object at 0x0000025184FA4DD8>, <__main__.Cat object at 0x0000025184FA4E10>]
Bhow Bhow!!
Meow Meow!!
工厂方法模式里面的抽象類不負責创建對象而只是提供共用接口,如AbstractMethod,主要是由其繼承之AbstractMethodConcrete具体子类来实现必要接口並負責创建其它對象之實例,可由工广方法抽象類AbstractMethod中的__init__中调用createObject()方法(*實則會反向呼叫AbstractMethodConcrete的createObject()實作方法)->addSets()方法被调用->sets列表增加元素。
优点:
- 可具更大的灵活性,因为它不是单纯用來创建單一类對象,而是取决工广方法抽象類之繼承具体子類來创建其它類之實例。
- 因为使用与创建对象的代码是分开的,故客户端可无需关心要传递哪些参数以实例化哪些對象,由于日後添加新类容易故可降低维护成本。
抽象工厂模式
UML图
示例:
# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod
class AbstractFactory(metaclass=ABCMeta): #抽象工广之抽象类
@abstractmethod
def createObject(self):
raise ImplementedError
class DogFactory(AbstractFactory): #工厂具体類1:狗類工广
def createObject(self):
return Dog()
class CatFactory(AbstractFactory): #工厂具体類2:猫類工广
def createObject(self):
return Cat()
class Animal(metaclass=ABCMeta): #抽象动物类
@abstractmethod
def do_say(self):
raise ImplementedError
class Dog(Animal): #具体子类1:狗类
def do_say(self):
print("Bhow Bhow!!")
class Cat(Animal): #具体子类1:猫类
def do_say(self):
print("Meow Meow!!")
#實際業務邏輯場景(client-site)
if __name__==’__main__’:
print("Animal has sets --", [DogFactory(), CatFactory()])
[obj.do_say() for obj in (factory.createObject() for factory in [DogFactory(), CatFactory()])]
輸出:
Animal has sets -- [<__main__.DogFactory object at 0x000001E34BF44D30>, <__main__.CatFactory object at 0x000001E34BF44D68>]
Bhow Bhow!!
Meow Meow!!
与工厂方法不同的是抽象工厂會包含許多專門具体類之工广,其作為專門创建某特定類型對象之用,在此將常用於應用開發之工厂方法与抽象工厂方法兩者區別如下:
- 工厂方法:
向客户端开放工广抽象类用於创建对象的接口,並透過继承工广抽象类之具体子类来创建其对象,常被使用於创建單一對象之用途中。
- 抽象工厂:
将创建对象的任务委託给其專門工广具体类來實現,常被使用於创建一系列不同對象之用途中。