什么是工厂模式
工厂表示一个负责创建其他类型对象的类。
一个工厂类有一个对象以及关联的多个方法,客户端通过传参调用这些方法,工厂类会创建所需类的对象,返回给客户端。
工厂模式的优点:
- 松耦合:对象创建可以独立于类的实现
- 客户端无需了解创建对象的类即可创建对象:客户端通过接口、方法和参数即可获得需要的对象,简化了客户端的实现
- 便于扩展:可以直接在工厂中添加其他类来创建新类型的对象,而客户端无需更改代码,通过改变参数即可
- 重用性:工厂可重用对象,而客户端直接创建则会每次都创建一个新对象
工厂模式分类
- 简单工厂模式:允许接口创建对象,但不暴露对象创建逻辑
- 工厂方法模式:允许对象创建对象,但使用哪个类创建,则由子类决定
- 抽象工厂模式:能够创建一系列相关对象,无需指定具体类接口
简单工厂模式
from abc import ABCMeta, abstractmethod
class Animal(metaclass=ABCMeta):
@abstractmethod
def do_say(self):
pass
class Dog(Animal):
def do_say(self):
print("wang wang")
class Cat(Animal):
def do_say(self):
print("meow meow")
# factory
class PetsFactory(object):
def make_sound(self, pet_kind):
eval(pet_kind)().do_say()
if __name__ == "__main__":
factory = PetsFactory()
pet_kind = input("what pet?")
factory.make_sound(pet_kind)
如上代码,对象通过工厂类PetsFactory
来创建,而又通过传入参数pet_kind
来控制对象的类型
工厂方法模式
- 我们定义接口来创建对象,但工厂本身并不负责创建对象,而是将这个任务交由子类来完成,即子类觉得实例化的类型
- Factory方法的创建是通过继承实现,而非实例化
- 设计具有可定制性。
from abc import ABCMeta, abstractmethod
class Section(metaclass=ABCMeta):
@abstractmethod
def describe(self):
pass
class PersonalSection(Section):
def describe(self):
print("personal")
class AlbumSection(Section):
def describe(self):
print("album")
class PatentSection(Section):
def describe(self):
print("patent")
class PublicationSection(Section):
def describe(self):
print("publication")
class Profile(metaclass=ABCMeta):
def __init__(self):
self.sections = []
self.createProfile()
@abstractmethod
def createProfile(self):
pass
def getSections(self):
return self.sections
def addSections(self, section):
self.sections.append(section)
class Linkedin(Profile):
def createProfile(self):
self.addSections(PersonalSection())
self.addSections(PatentSection())
self.addSections(PublicationSection())
class Facebook(Profile):
def createProfile(self):
self.addSections(PersonalSection())
self.addSections(AlbumSection())
if __name__ == "__main__":
profile_type = input("facebook or linkedin?")
profile = eval(profile_type.lower())()
print("creating profile:", type(profile).__name__)
print("sections of profile:", profile.getSections())
上述代码中,通过选择不同的creator
,从而实例化出不同的section对象
工厂方法模式的优点
- 更好的灵活性,代码通用性更高。因为并非单纯地实例化某个类,而是通过接口来决定类的实例化
- 松耦合。创建对象代码与使用代码分离,客户端不关心需要传哪些参数,甚至不用关心需要实例化哪些类。而添加新类更容易,降低维护成本
抽象工厂模式
from abc import ABCMeta, abstractmethod
class PizzaFactory(metaclass=ABCMeta):
@abstractmethod
def createVegPizza(self):
pass
@abstractmethod
def createNonVegPizza(self):
pass
class IndianPizzaFactory(PizzaFactory):
def createVegPizza(self):
return DeluxVeggiePizza()
def createNonVegPizza(self):
return ChickenPizza()
class USPizzaFactory(PizzaFactory):
def createVegPizza(self):
return MexicanVegPizza()
def createNonVegPizza(self):
return HamPizza()
class VegPizza(metaclass=ABCMeta):
@abstractmethod
def prepare(self, VegPizza):
pass
class NonVegPizza(metaclass=ABCMeta):
@abstractmethod
def serve(self, VegPizza):
pass
class DeluxVeggiePizza(VegPizza):
def prepare(self):
print("prepare", type(self).__name__)
class ChickenPizza(NonVegPizza):
def serve(self, VegPizza):
print(type(self).__name__, "is served with chicken on", type(VegPizza).__name__)
class MexicanVegPizza(VegPizza):
def prepare(self):
print("prepare", type(self).__name__)
class HamPizza(NonVegPizza):
def serve(self, VegPizza):
print(type(self).__name__, "is served with ham on", type(VegPizza).__name__)
class PizzaStore:
def __init(self):
pass
def makePizzas(self):
for factory in [IndianPizzaFactory(), USPizzaFactory()]:
self.factory = factory
self.NonVegPizza = self.factory.createNonVegPizza()
self.VegPizza = self.factory.createVegPizza()
self.VegPizza.prepare()
self.NonVegPizza.serve(self.VegPizza)
pizza = PizzaStore()
piza.makePizzas()
工厂方法与抽象工厂方法对比
工厂方法 | 抽象工厂方法 |
---|---|
开放了一个创建对象的接口 | 包含一个或多个工厂方法来创建一系列对象 |
使用继承和子类来决定创建哪个对象 | 使用组合将创建对象的任务委托给其他类 |
用于创建一个产品 | 用于创建相关产品的系列 |