HOME/Articles/

创建型模式

Article Outline

单例模式

title

  • 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点

  • 适用性:

    1. 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

    2. 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时

class Singleton(object):
    _instance = None

    def __new__(cls):
        if cls._instance == None:
            cls._instance = object.__new__(cls)
        return cls._instance

class A(Singleton):
    pass

if __name__ == '__main__':
    print("instantiate s1")
    s1 = A()
    print("s1 address: {}\n".format(s1))

    print("instantiate s2")
    s2 = A()
    print("s2 address: {}".format(s2))
    print("s1 address: {}".format(s1))
    assert s1 == s2, "s1 != s2"
    assert s1 is s2, "s1 is s2"

工厂方法模式

title

  • 意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类

  • 适用性:

    1. 当一个类不知道它所必须创建的对象的类时

    2. 当一个类希望由它的子类来指定它所创建的对象时

    3. 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时

from math import pi

class ShapeFactory:
    def __init__(self, paramter):
        self.paramter = paramter

    def get_paramter(self):
        return "The paramter is {}".format(self.paramter)

    def get_perimeter(self):
        raise NotImplementedError

class CircleFactory(ShapeFactory):
    def get_perimeter(self):
        return 2 * pi * self.paramter

class SquareFactory(ShapeFactory):
    def get_perimeter(self):
        return 4 * self.paramter

if __name__ == '__main__':
    circleFactory = CircleFactory(1)
    squareFactory = SquareFactory(2)
    print("The circle paramter = {}".format(circleFactory.get_paramter()))
    print("The circle perimeter = {}".format(circleFactory.get_perimeter()))
    print("The square paramter = {}".format(squareFactory.get_paramter()))
    print("The square perimeter = {}".format(squareFactory.get_perimeter()))

抽象工厂模式

title

  • 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

  • 适用性:

    1. 一个系统要独立于它的产品的创建、组合和表示时

    2. 一个系统要由多个产品系列中的一个来配置时

    3. 当你要强调一系列相关的产品对象的设计以便进行联合使用时

    4. 当你提供一个产品类库,而只想显示它们的接口而不是实现时

from abc import * 

class AbstractFactory(metaclass = ABCMeta):

    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2

    @abstractmethod
    def add(self):
        pass

    @abstractmethod
    def sub(self):
        pass

 # ConcreteFactory1
class Calculator(AbstractFactory):
    def add(self):
        return Add(self.num1, self.num2).add_method()

    def sub(self):
        return Sub(self.num1, self.num2).sub_method()

# ConcreteFactory2
class ParamterCalculator(AbstractFactory):
    def add(self):
        return ParamterAdd(self.num1, self.num2).add_method()

    def sub(self):
        return ParamterSub(self.num1, self.num2).sub_method()

# AbstractProductA
class AbstractAdd(metaclass = ABCMeta):
    def __init__(self,  num1, num2):
        self.num1 = num1
        self.num2 = num2

    @abstractmethod
    def add_method(self):
        pass

# ProductA1
class Add(AbstractAdd):
    def add_method(self):
        print("The Method is Add")
        return self.num1 + self.num2

# ProductA2
class ParamterAdd(AbstractAdd):
    def add_method(self):
        print("The Method is ParamterAdd")
        print("{} + {} = {}".format(self.num1, self.num2, self.num1 + self.num2))
        return self.num1 + self.num2    

# AbstractProductB
class AbstractSub(metaclass = ABCMeta):
    def __init__(self,  num1, num2):
        self.num1 = num1
        self.num2 = num2

    @abstractmethod
    def sub_method(self):
        pass

# ProductB1
class Sub(AbstractSub):
    def sub_method(self):
        print("The Method is Sub")
        return self.num1 - self.num2

# ProductB2
class ParamterSub(AbstractSub):
    def sub_method(self):
        print("The Method is ParamterSub")
        print("{} - {} = {}".format(self.num1, self.num2, self.num1 - self.num2))
        return self.num1 - self.num2    

if __name__ == '__main__':
    calculator = Calculator(1,2)
    assert calculator.add() == 1+2, "calculator: add method error"
    assert calculator.sub() == 1-2, "calculator :sub method error"

    paramterCalculator = ParamterCalculator(3,4)
    paramterCalculator.add()
    paramterCalculator.sub()

建造者模式

title

  • 意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

  • 适用性:

    1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时

    2. 当构造过程必须允许被构造的对象有不同的表示时

from abc import *

class Director:
    def __init__(self, building):
        self.building = building

    def show(self):
        self.building.show()

class Builder(metaclass = ABCMeta):
    @abstractmethod
    def show(self):
        pass

class House(Builder):
    def show(self):
        print("The building is House")

class Apartment(Builder):
    def show(self):
        print("The building is Apartment")

if __name__ == '__main__':
    house = House()
    apartment = Apartment()
    house_director = Director(house)
    house_director.show()
    apartment_director = Director(apartment)
    apartment_director.show()

原型模式

title

  • 意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

  • 适用性:

    1. 当要实例化的类是在运行时刻指定时,例如,通过动态装载

    2. 或者为了避免创建一个与产品类层次平行的工厂类层次时

    3. 或者当一个类的实例只能有几个不同状态组合中的一种时

      建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

import copy

class Prototype:
    def __init__(self):
        self._objects = {}

    def register_object(self, name, obj):
        self._objects[name] = obj

    def unregister_object(self, name):
        del self._objects[name]

    def clone(self, name, **attr):
        obj = copy.deepcopy(self._objects.get(name))
        obj.__dict__.update(attr)
        return obj

class A:
    def __str__(self):
        return "I am A"

if __name__ == '__main__':
    a= A()
    prototype= Prototype()
    prototype.register_object('a', a)
    b= prototype.clone('a', param1 = 1, param2 = 2, param3 = 3)

    print(a)
    print(b.param1, b.param2, b.param3)