8

Python 设计模式——工厂模式

 3 years ago
source link: https://rollingstarky.github.io/2020/12/22/python-design-patterns-factory-pattern/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Python 设计模式——工厂模式

发表于 2020-12-22

| 分类于 Python

| 0

| 阅读次数: 2

字数统计: 5.4k

|

阅读时长 ≈ 0:05

在面向对象编程中,工厂表示一个负责创建其他类型的对象的类。
通常作为工厂的类会实现多个关联的方法,客户端通过某些参数调用这些方法,工厂则负责创建对应类型的对象并返回给客户端。

工厂模式的优点:

  • 松耦合。对象的创建独立于类的实现
  • 客户端无需了解创建对象的类,只需知道需要传递的接口、方法和参数即可。简化了客户端的实现
  • 可以轻松地在工厂中添加其他类来创建其他类型的对象,无需更改客户端代码
  • 工厂可以重用现有的对象

简单工厂模式

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")


class ForestFactory:
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\n")
ff.make_sound(animal)
$ python make_sound.py
Which animal should make sound, Dog or Cat
Dog
Bhow Bhow
$ python make_sound.py
Which animal should make sound, Dog or Cat
Cat
Meow Meow

工厂方法模式

工厂方法模式的特点:

  • 定义一个接口来创建对象,但工厂本身并不负责创建动作,而是由其子类决定实例化哪些类
  • 工厂方法的创建是通过继承而不是通过实例化来完成的
  • 工厂方法使设计更具有定制性。可以返回相同的实例或子类
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)


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 you'd like to create?\n[LinkedIn or FaceBook] ")
profile = eval(profile_type.lower())()
print("Creating Profile...", type(profile).__name__)
print("Profile has sections --", profile.getSections())
$ python profile.py
Which Profile you'd like to create?
[LinkedIn or FaceBook] LinkedIn
Creating Profile... linkedin
Profile has sections -- [<__main__.PersonalSection object at 0x7f3d25e53c70>, <__main__.PatentSection object at 0x7f3d25e53ca0>, <__main__.PublicationSection object at 0x7f3d25e53df0>]

UML

Profile 抽象类代表 Creator,提供了 createProfile() 工厂方法,用于创建带有适当板块的个人信息界面。但 Profile 并不清楚某个特定界面应该具有哪些板块,如 Facebook 需要提供个人信息板块和相册区。createProfile() 工厂方法实际是由 Profile 的子类去实现的。

两个 Profile 的子类 linkedin 和 facebook 代表 ConcreteCreator,每个类都实现了 createProfile 方法,该方法在运行时创建多个板块(ConcreteProducts)。

工厂方法模式的优点

  • 强大的灵活性,代码更加通用。实现哪些类取决于接口(Product),而不是 ConcreteProduct 类
  • 松耦合。创建对象的代码与使用对象的代码是分离的。客户端不需要关心传递哪些参数以及需要实例化哪些类

抽象工厂模式

抽象工厂模式的主要目的是提供一个接口来创建一系列相关的对象,而无需指定具体的类。因此可以帮助客户端一次使用来自一个产品/系列的多个对象。比如正在开发的应用是平台无关的,则需要对不同平台下的各种依赖项(包括操作系统、文件系统调用等)进行抽象处理,由抽象工厂为各个平台创建所需的服务,客户端就不必直接创建平台对象了。

UML

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 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()

# => Prepare DeluxVeggiePizza
# => ChickenPizza is served with Chicken on DeluxVeggiePizza
# => Prepare MexicanVegPizza
# => HamPizza is served with Ham on MexicanVegPizza
工厂方法与抽象工厂方法的比较
工厂方法 抽象工厂方法 向客户端开放了一个创建对象的方法 包含一个或多个工厂方法来创建一个系列的相关对象 使用继承和子类决定要创建哪个对象 使用组合将创建对象的任务委托给其他类 工厂方法用于创建一个产品 抽象工厂方法用于创建相关产品的系列

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK