工厂模式
一、工厂模式的优点
1.松耦合,即对象的创建可以独立于类的实现
2.客户端无需了解创建对象的类,但是可以照样使用它来创建对象,只需要知道需要传递的接口、方法和参数,就能够创建所需类型的对象。简化了客户端的实现
3.可以轻松地在工厂中添加其他类来创建其他类型的对象,无需更改客户端代码,有时客户端只需传递另一个参数就行
4.工厂还可以重用现有对象。但是,如果客户端直接创建对象的话,总是创建一个新对象
二、工厂模式
*、简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑
*、工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则是由子类决定的
*、抽象工厂模式:是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口,该模式能够提供其他工厂的对象,在其内部 创建其他对象
1、简单工厂模式
UML如下
示例代码如下:
# -*- coding:utf-8 -*- from abc import ABCMeta, abstractmethod class Animal(metaclass=ABCMeta): @abstractmethod def do_say(self): pass class Dog(Animal): def do_say(self): print("dog bhow bhow") class Cat(Animal): def do_say(self): print("cat meow meow") class ForestFactory(object): def make_sound(self, object_type): return eval(object_type)().do_say() if __name__ == '__main__': ff = ForestFactory() animal = input("which animal should make_sound Dog or Cat?") ff.make_sound(animal)
创建一个为Animal的抽象产品,带有方法do_say(),利用Animal接口创建了两种产品(Dog,Cat),并实现了do_say方法来提供这些动物相应的叫声。ForestFactory是一个带有make_sound()方法的工厂,根据客户端传递的参数类型,可以在运行时创建适当的Animal实例,并输出正确的声音。
2、工厂方法模式
1.了解工厂方法模式
*、定义了一个接口来创建对象,但是工厂本身并不复杂创建对象,而是将这一任务交由子类来完成,即子类决定了要实例化哪些类
*、Factory方法的创建是通过继承而不是实例化来完成的
*、工厂方法使设计更加具有可定制性,它可以返回相同的实例或子类,而不是某种类型的对象
UML如下:
在该UML中,有一个包含factoryMethod()方法的抽象类Creator,factoryMethod()方法负责创建指定类型的对象。ConcreteCreator类提供了一个实例Creator抽象类的factoryMethod()方法,这种方法可以在运行时修改已创建的对象。ConcreteCreator创建ConcreteProduct,并确保其创建的对象实现了Product,同时为Product接口中的所有方法提供相应的实现。
简言之,Creator接口的factoryMethod()方法和ConcreteCreator类共同决定了要创建Product的哪个子类。因此,工厂方法模式定义了一个接口来创建对象,但具体实例化哪个类则是由它的子类决定的。
2.实现工厂方法
# -*- coding:utf-8 -*- from abc import ABCMeta, abstractmethod # 接口Product class Section(metaclass=ABCMeta): @abstractmethod def describe(self): pass # 定义多个ConcreteProduct class PersonalSection(Section): def describe(self): print("Personal Section") class AlbumSection(Section): def describe(self): print("Album Section") class PatentSection(Section): def describe(self): print("Patent Section") class PublicationSection(Section): def describe(self): print("Publication Section") # 创建了一个抽象类(Creator) Profile,提供了一个工厂方法createProfile() 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) # 创建了两个ConcreteCreator,即linkedin, facebook,每个类都实现了createProfile抽象方法, # 由该方法在运行时实际创建(实例化)多个区(ConcreteProduct) 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("which profile LinkedIn or FaceBook?") profile = eval(profile_type.lower())() print("creating profile..", type(profile).__name__) print("profile has sections --", profile.getSections())
上述代码段的输出如下:
3、工厂方法模式的优缺点
a、使得代码更加通用,不是单纯地实例化某个类。实现哪些类取决于接口(Product),而不是ConcreteProduct类
b、它们是松耦合的,创建对象的代码与使用它们的代码的分开的。客户端完全不用关心要传递哪些参数以及需要实例化哪些类。由于添加新类更加容易,降低了维护成本。
3、抽象工厂方法模式
1、了解抽象工厂模式
抽象工厂的主要目的是提供一个接口来创建一系列相关对象,而无需指定具体的类。工厂方法将创建实例的任务委托给了子类,而抽象工厂方法的目标是创建一系列相关对象。
2、UML
在该UML中,ConcreteFactory1和ConcreteFactory2是通过AbstractFactory接口创建的,并创建实例ConcreteProduct1和ConcreteProduct2、AnotherConcreteProduct1和 AnotherConcreteProduct2;ConcreteProduct1和ConcreteProduct2是通过AbstractProduct接口创建的,而AnotherConcreteProduct1和AnotherConcreteProduct2则是通过 AnotherAbstractProduct接口创建的。
实际上,抽象工厂模式不仅确保客户端与对象的创建相互隔离,同时还确保客户端能够使用创建的对象。但是,客户端只能通过接口访问对象。
3、实现抽象工厂模式
# -*- coding:utf-8 -*- from abc import ABCMeta, abstractmethod # AbstractFactory class PizzaFactory(metaclass=ABCMeta): # 具有两个抽象方法,它们需要通过ConcreteFactory实现 @abstractmethod def creatVegPizza(self): pass @abstractmethod def creatNonVegPizza(self): pass # 两个ConcreteFactory,实现了抽象方法 class IndianPizzaFactory(PizzaFactory): def creatVegPizza(self): return DeluxVeggiePizza() def creatNonVegPizza(self): return ChickenPizza() class USPizzaFactory(PizzaFactory): def creatVegPizza(self): return MexicanVegPizza() def creatNonVegPizza(self): return HamPizza() # 定义抽象类AbstractProduct class VegPizza(metaclass=ABCMeta): @abstractmethod def prepare(self, VegPizza): pass # 定义抽象类AnotherAbstractProduct class NonVegPizza(metaclass=ABCMeta): @abstractmethod def serve(self, VegPizza): pass # 定义ConcreteProduct1 class DeluxVeggiePizza(VegPizza): def prepare(self): print("prepare", type(self).__name__) # 定义ConcreteProduct2 class ChickenPizza(NonVegPizza): def serve(self, VegPizza): print(type(self).__name__, "is served with chicken on", type(VegPizza).__name__) # AnotherConcreteProduct1 class MexicanVegPizza(VegPizza): def prepare(self): print("prepare", type(self).__name__) # AnotherConcreteProduct2 class HamPizza(NonVegPizza): def serve(self, VegPizza): print(type(self).__name__, "is served with chicken 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.creatNonVegPizza() self.VegPizza = self.factory.creatVegPizza() self.VegPizza.prepare() self.NonVegPizza.serve(self.VegPizza) if __name__ == '__main__': pizza = PizzaStore() pizza.makePizzas()
运行结果如下:
工厂方法与抽象工厂对比: