一、了解工厂模式
1.优点
1.1 松耦合,即对象的创建可以独立于类的实现。
1.2 客户端无需了解创建对象的类,但是照样可以使用它来创建对象。它只需要知道传递的接口、方法、参数,就能够创建所需类型的对象。这简化了客户端的实现。
1.3 可以轻松地在工厂中添加其他类来创建其他类型的对象,而这无需更改客户端代码。最简单的情况下,客户端只需要传递另一个参数就可以了。
1.4 工厂还可以重用现有对象。但是,如果客户端直接创建对象的话,总是创建一个新对象。
2.分类
2.1 简单工厂模式:允许接口创建对象,但不会暴露对象的创建逻辑。
2.2 工厂方法模式:允许接口创建对象,但使用哪个类来创建对象,则是交由子类决定。
2.3 抽象工厂模式: 抽象工厂是一个能够创建一系列相关的对象而无需指定/公开其具体类的接口。该模式能够提供其他工厂的对象,在其内部创建其他对象。
二、简单工厂模式
1.UML图
2.代码
# -*- 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("Bhow Bhow!!")
# 猫类,继承动物类
class Cat(Animal):
def do_say(self):
print("Meow Meow!!")
## forest factory defined
class ForestFactory(object):
def make_sound(self, object_type):
print(eval(object_type))
return eval(object_type)().do_say()
## client code
if __name__ == '__main__':
ff = ForestFactory()
animal = input("Which animal should make_sound Dog or Cat?")
ff.make_sound(animal)
3.解析
3.1 代码中的ForestFactory就是传说中的工厂,我们输入,Cat或者Dog,就会通过它直接调用具体的类中的make_sound方法。
3.2 eval函数
eval函数可以将字符串直接当然有效的表达式,当然如果此处不用eval函数也可以采用if elif else 的形式进行对输入的判定,和类方法的调用。但此例中eval方式显然更加优雅。
三、工厂方法模式
1.概念
1.1 定义接口来创建对象,工厂本身并不负责创建对象,而是将这一任务交由子类完成,即子类决定了要实例化哪些类。
1.2 Factory方法的创建是通过继承而不是通过实例化来完成的。
1.3 工厂方法使设计更加具有可定制性。它可以返回相同的实例或子类,而不是某种类型的对象(就像简单工厂方法那样)
2.UML图
3.代码
# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod
# 抽象基类(部分类)
class Section(metaclass=ABCMeta):
@abstractmethod
def describe(self):
pass
# 子类,继承基类(个人部分类)
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")
# 工厂方法类:只提供了接口,并没有实际创建类(简历类:提供简历中的接口)
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)
# 继承Profile,实例化具体类(实例化了具体创建哪些简历)
class linkedin(Profile):
def createProfile(self):
self.addSections(PersonalSection())
self.addSections(PatentSection())
self.addSections(PublicationSection())
# 继承Profile,实例化具体类
class facebook(Profile):
def createProfile(self):
self.addSections(PersonalSection())
self.addSections(AlbumSection())
if __name__ == '__main__':
profile_type = input("Which Profile you'd like to create? [LinkedIn orFaceBook]")
profile = eval(profile_type.lower())()
print("Creating Profile..", type(profile).__name__)
print("Profile has sections --", profile.getSections())
4.解析
4.1 工厂方法里面的工厂不创建类只提供接口。
4.2 当我们输入Linkedin后发生了什么?
4.2.1 linkedin类被实例化:Profile中的__init__中的创建createProfile被调用(linkedin的createProfile被调用)->addSections被调用->section列表增加
4.2.2 这里再次强调,Profile只提供了相关接口,实现是由linkedin子类来做的。
5.优点
5.1 它具有更大的灵活性,使得代码更加通用,因为它不是单纯地实例化某个类。这样实现哪些类取决于接口。
5.2 松耦合,因为创建对象的代码与使用它的代码是分开的。客户端无需关心传递哪些参数以及需要实例化哪些类。由于添加新类更加容易,所以降低了维护成本。
四、抽象工厂模式
1.UML图
2.代码
# -*- coding: UTF-8 -*-
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()
pizza.makePizzas()
3.解析
3.1 与工厂方法的主要区别是,将工厂多了一层抽象。它创建的不是一个对象是一类对象。
3.2本例中,当创建工厂后,会同步创建蔬菜披萨和非蔬菜披萨两个类。
五、工厂方法与抽象工厂方法
工厂方法:
1.它向客户端开放了一个创建对象的方法。
2.它使用继承和子类来决定要创建哪个对象
3.工厂方法用于创建一个产品
抽象工厂方法:
1.抽象工厂包换了一个或者多个工厂方法来创建一系列的相关对象
2.它使用组合将创建对象的任务委托给其他类
3.抽象工厂用于创建相关产品系列
本系列项目代码地址:Python-design-pattern