设计模式---工厂模式

0 概念

介绍如何使用工厂设计模式(工厂方法和抽象工厂)来初始化对象,并说明与直接实例化对象相比,使用工厂设计模式的优势.

描述:客户端可以请求一个对象,而无需知道这个对象来自哪里;也就是说,使用哪个类来生成这个对象.
思想:简化对象的创建.
好处:基于一个中心化函数创建对象,更容易追踪创建了哪些对象.通过将创建对象的代码和适用对象的代码解耦,工厂能降低应用维护的复杂度.
形式:工厂形式有2种:

  1. 工厂方法(Factory Method),他是一个函数(或者说方法),对不同的输入参数返回不同的对象;
  2. 抽象工厂,他是一组用于创建一系列相关事物对象的工厂方法.

1 工厂方法(简单工厂模式)

1.1 定义

在工厂方法模式中,我们执行单个函数,传入参数,但不要求知道对象来自哪里和如何实现的细节.

1.2 例子

1.2.1 现实例子

塑料玩具制造. 制造塑料玩具的压塑粉都是一样的,但使用不同的塑料模具就能产出不同的外形.
例如,一个工厂方法,输入目标外形(鸭子或小车)的名称,输出是要求的塑料外形.
工厂模式现实例子---鸭子和小车
工厂模式现实例子---鸭子和小车

1.2.2 软件例子

Django框架使用工厂方法模式创建表单字段. Django的forms模块支持不同种类字段(CharField,EmailField)的创建和定制(max_length,min_length).

1.2.3 应用例子

应用:

  1. 创建对象的代码分布在多个地方无法追踪对象.
  2. 要将对象的创建和使用解耦.
  3. 工厂方法(简单工厂模式)在必要时创建新的对象,从而调高性能和内存使用率. 直接实例化创建对象的话,每次创建对象要分配额外的内存(除非使用缓存,不用缓存的话用两个内存地址保存实例化对象的).

补充:
创建多个工厂方法也没问题,对相似的对象创建进行逻辑分组,每个工厂方法负责一个分组.

1.3 简单工厂模式代码实例1

简单来说就是黑科技,输入进去一个东西,经过用户也不知道的加工,出来另一个东西,加工时调用类.

class Person:
    def __init__(self):
        self.name = None
        self.gender = None
        
    def getName(self):
        return self.name
        
    def getGender(self):
        return self.gender


class Male(Person):
    def __init__(self, name):
        print
        "Hello Mr." + name


class Female(Person):
    def __init__(self, name):
        print
        "Hello Miss." + name


class Factory:
    def getPerson(self, name, gender):
        if gender == 'M':
            return Male(name)
        if gender == 'F':
            return Female(name)


if __name__ == '__main__':
    factory = Factory()
    person = factory.getPerson("Chetan", "M")

1.4 简单工厂模式代码实例2

class Opeartor(object):
    """docstring for Operator"""
    def __init__(self,NumberA = 0,NumberB = 0):
        super(Opeartor,self).__init__()
        self.NumberA = NumberA
        self.NumberB = NumberB

def GetResult(self):
    pass

class AddOp(Opeartor):
    """docstring for AddOp"""
    def GetResult(self):
    
    	return int(float(self.NumberA) + float(self.NumberB))

class MinusOp(Opeartor):
    """docstring for MinusOp"""
	def GetResult(self):
    	return int(float(self.NumberA) - float(self.NumberB))

class MultiOp(Opeartor):
    """docstring for MultiOp"""
	def GetResult(self):
    	return int(float(self.NumberA) * float(self.NumberB))

class DivideOp(Opeartor):
    """docstring for DivideOp"""
    def GetResult(self):
        try:
            return float(float(self.NumberA) / float(self.NumberB) * 1.0)
        except ZeroDivisionError as e:
            print("DivideOp error,{0}".format(e))

class OperatorFactory(object):
    """docstring for OperatorFactory"""
    def ChooseOperator(self,op):
        if op == '+':
            return AddOp()
        if op == '-':
            return MinusOp()
        if op == '*':
            return MultiOp()
        if op == '/':
            return DivideOp()
            
if __name__ == '__main__':
    ch = ''
    while ch != 'Q':
        NumberA = input('Please input NumberA:')
        op = input('Please input operator:')
        NumberB = input('Please input NumberB:')
        factory = OperatorFactory()
        opType = factory.ChooseOperator(op)
        opType.NumberA = NumberA
        opType.NumberB = NumberB
        print('The result is:{0}'.format(opType.GetResult()))
        print('\n#-- input q to exit any key to continue')

        try:
            ch = str(input('大写输入Q退出:'))
        except Exception as e:
            print('Get input error:{0}'.format(e))
            print('User default value to ch')
            ch = ''

2 抽象工厂

2.1 概念

抽象工厂设计模式是抽象方法的一种泛化。 概括来说,一个抽象工厂是(逻辑上的)一组工作方法。 其中每个工厂方法负责产生不同种类的对象。

2.2 例子

2.2.1 现实例子

汽车制造业采用抽象工厂的思想。冲压不同汽车模型的部件(车门、仪表盘、车篷等)使用机件相同。机件装配起来的模型随时可配置,并且易于改变。
抽象模型现实例子---汽车装配

2.2.2 软件例子

django_factory 是一个用于在测试中创建Django模型的抽闲工厂实现,可用来测试专有属性的模型创建实例. 这能让测试代码的可读性更高,并且能避免共享不必要的代码.

2.2.3 应用例子

因为抽象工厂模式是工厂方法模式的一种泛化,所以他能提供相同的好处:

  1. 让对象的创建更容易追踪;
  2. 将对象创建与使用解耦;
  3. 提供优化内存占用和应用性能的潜力.

问:什么时候使用工厂方法,什么时候使用抽象工厂?
答:通常一开始的时候使用工厂方法,因为更简单.
  如果后期发现应用需要很多弓藏方法,那么将创建一系列对象的过程合并在一起更合理,从而产生抽象工厂.

优点:
在使用工厂方法时从用户视角感受不到,即抽象工厂能通过改变激活的工厂方法动态改变引用行为.

2.3 抽象工厂模式代码实例

# 抽象工厂模式
import random

class PetShop:
    """宠物商店"""
    def __init__(self,animal_factory = None):
        """宠物工厂是我们的抽象工厂,我们可以随意设置"""
        self.pet_factory = animal_factory
    def show_pet(self):
        """使用抽象工厂创建并显示一个宠物"""

        pet = self.pet_factory.get_pet()
        print('我们有一个可爱的{}'.format(pet))
        print('它说{}'.format(pet.speak()))
        print('我们还有{}'.format(self.pet_factory.get_food()))

# 工厂生产的事物
class Dog:
    def speak(self):
        return '汪'

    def __str__(self):
        return 'Dog'

class Cat:
    def speak(self):
        return '喵'

    def __str__(self):
        return 'Cat'

# Factory classes
class DogFactory:
    def get_pet(self):
        return Dog()

    def get_food(self):
        return '狗食'
        
class CatFactory:
    def get_pet(self):
        return Cat()

    def get_food(self):
        return '猫粮'
        
#随机创建合适的工厂
def get_factory():
    """让我们动起来!"""
    return random.choice([DogFactory,CatFactory])()

#多个工厂显示宠物
if __name__ == '__main__':
    for i in range(4):
        shop = PetShop(get_factory())
        shop.show_pet()
        print('=' * 20)

3 补充

工厂方法实例补充

抽象工厂模式实例补充

补充链接1
补充链接2---工厂模式
补充链接3---简单工厂模式
补充链接4---抽象工厂模式

4 小结

工厂方法和抽象共产设计模式的异同:
相同:
应用场景:

  1. 想要追踪对象的创建时
  2. 想要将对象的创建与使用解耦时
  3. 想要优化应用的性能和资源占用时

不同:
工厂方法设计模式的实现是一个不属于任何类的单一函数,负责单一种类对象(一个形状,一个连接点或者是其他对象)的创建.

《精通python设计模式》中的工厂模式提供了访问xml和json文件的能力.

抽象工厂设计模式的实现是同属于单个类的许多个工厂方法用于创建一系列种类的相关对象(一辆车的部件,一个游戏的环境或者其他对象).

posted on 2019-06-25 11:48  流云封心  阅读(69)  评论(0)    收藏  举报