首页 > 技术文章 > 设计模式之创建型模式

longyunfeigu 2018-08-27 16:39 原文

对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。这里有6个具体的创建型模式可供研究,它们分别是:

  1. 工厂模式(Simple Factory);
  2. 工厂方法模式(Factory Method);
  3. 抽象工厂模式(Abstract Factory);
  4. 创建者模式(Builder);
  5. 原型模式(Prototype);
  6. 单例模式(Singleton)

工厂模式

定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类
组成:工厂类 + 抽象产品类 + 具体产品类

from abc import ABCMeta, abstractclassmethod

class Animal(object):
    @abstractclassmethod
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        print('汪汪汪')

class Cat(Animal):
    def speak(self):
        print('喵喵喵')

class Factory(object):
    def create_animal(self, atype):
        if atype == 'cat':
            obj = Cat()
        elif atype == 'dog':
            obj = Dog()
        return obj
############## 使用  ####################
f = Factory()
animal = f.create_animal('cat')
animal.speak()

优点:隐藏了对象创建的实现细节;每增加一个产品的时候客户端不需要更改代码结构
缺点:每增加一个产品就需要更改工厂代码,不符合开放封闭原则;

工厂方法模式

产品比较少的情况,使用简单工厂模式比较合理。当产品很多,而且未来可能会更多的情况下,这时候可以考虑工厂方法模式。
抽象工厂类 + 具体工厂类 + 抽象产品类 + 具体产品类

from abc import ABCMeta, abstractclassmethod

class CPU(metaclass=ABCMeta):
    @abstractclassmethod
    def run(self):
        pass

class IntelCpu(CPU):
    def run(self):
        print('intel cpu run')
class AmdCpu(CPU):
    def run(self):
        print('amd cpu run')

class CpuFactory(metaclass=ABCMeta):
    @abstractclassmethod
    def create_cpu(self):
        pass

class IntelCpuFactory(CpuFactory):
    def create_cpu(self):
        return IntelCpu()

class AmdCpuFactory(CpuFactory):
    def create_cpu(self):
        return AmdCpu()

################# 使用  ###############
f = IntelCpuFactory()
cpu = f.create_cpu()
cpu.run()

f = AmdCpuFactory()
cpu = f.create_cpu()
cpu.run()
  1. 工厂方法模式相比简单工厂模式将每个具体产品都对应一个具体工厂。
  2. 在简单工厂模式中,一个工厂可以建造空调,洗衣机,电脑等,现在对工厂细化分工,也就是单一职责化,这样每个工厂生产各自特定的产品。当增加一个产品,只需要增加对应的一个具体产品类+具体工厂类,不需要在原有的代码上做增删改查。
  3. 工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,或者说是同一个产品等级

优点:每个具体产品都对应一个具体工厂类,不需要修改工厂类代码;隐藏了对象创建的实现细节
缺点:每增加一个具体产品类,就必须增加一个相应的具体工厂类

抽象工厂模式

工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类,或者说抽象工厂生产的产品对象是一个由多个组件对象组成的对象。
组成部分:抽象工厂类 + 具体工厂类 + 抽象产品类 + 具体产品类 + 客户端(用于生产包含多个组件的产品对象)
相比工厂方法模式,抽象工厂模式中的每个具体工厂都产生一套产品
当你发现,有一个接口可以有多种实现的时候,可以考虑使用工厂方法来创建实例。
当你发现,有一组接口可以有多种实现方案的时候,可以考虑使用抽象工厂创建实例组

from abc import ABCMeta, abstractclassmethod

################# 抽象产品  ###############
class CPU(metaclass=ABCMeta):
    @abstractclassmethod
    def show_cpu(self):
        pass

class Mainboard(metaclass=ABCMeta):
    @abstractclassmethod
    def show_mainboard(self):
        pass

############### 具体产品  ##############
class IntelMainboard(Mainboard):
    def show_mainboard(self):
        print('intel mainboard')
class AmdMainboard(Mainboard):
    def show_mainboard(self):
        print('amd mainboard')

class IntelCpu(Mainboard):
    def show_cpu(self):
        print('intel cpu')

class AmdCpu(Mainboard):
    def show_cpu(self):
        print('amd cpu')
############### 抽象工厂  ##################
class CpuFactory(metaclass=ABCMeta):
    @abstractclassmethod
    def create_cpu(self):
        pass

    @abstractclassmethod
    def create_mainboard(self):
        pass

############### 具体工厂 ####################
class IntelCpuFactory(CpuFactory):
    def create_cpu(self):
        return IntelCpu()
    def create_mainboard(self):
        return IntelMainboard()

class AmdCpuFactory(CpuFactory):
    def create_cpu(self):
        return AmdCpu()
    def create_mainboard(self):
        return AmdMainboard()

class ComputerEngineer(object):
    def create_computer(self, f):
        self.cpu = f.create_cpu()
        self.mainboard = f.create_mainboard()
################# 使用  ###############
f = AmdCpuFactory()
cf = ComputerEngineer()
computer = cf.create_computer(f)

建造者模式

内容:将一个复杂对象的构建与它表示分离,使得同样的构建过程可以创建不同的表示。例如,创建一个人对象,这个对象的属性可能是有不同表示,有黑人,黄种人,白人等,有胖子和瘦子等

建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象,而抽象工厂模式着重于多个系列的产品对象。

组成:抽象建造者类 + 具体建造者类 + 指挥者类 + 产品类

# 产品类
class Person(object):
    def __init__(self, head=None, body=None, arm=None, leg=None):
        self.head = head
        self.body = body
        self.arm = arm
        self.leg = leg

    def __str__(self):
        return '%s-%s-%s-%s'%(self.head, self.body, self.arm, self.leg)

# 建造者基类
class PersonBuilder():
    def BuildHead(self):
        pass

    def BuildBody(self):
        pass

    def BuildArm(self):
        pass

    def BuildLeg(self):
        pass


# 胖子建造者类
class PersonFatBuilder(PersonBuilder):
    type = '胖子'
    def __init__(self):
        self.person = Person()
    def BuildHead(self):
        print("构建%s的头" % self.type)
        self.person.head = "%s的头" % self.type
    def BuildBody(self):
        print("构建%s的身体" % self.type)
        self.person.body = "%s的身体" % self.type

    def BuildArm(self):
        print("构建%s的手" % self.type)
        self.person.arm = "%s的手" % self.type

    def BuildLeg(self):
        print("构建%s的脚" % self.type)
        self.person.leg = "%s的脚" % self.type


# 瘦子建造者类
class PersonThinBuilder(PersonBuilder):
    type = '瘦子'

    def __init__(self):
        self.person = Person()
    def BuildHead(self):
        print("构建%s的头" % self.type)
        self.person.head = "%s的头" % self.type
    def BuildBody(self):
        print("构建%s的身体" % self.type)
        self.person.body = "%s的身体" % self.type

    def BuildArm(self):
        print("构建%s的手" % self.type)
        self.person.arm = "%s的手" % self.type

    def BuildLeg(self):
        print("构建%s的脚" % self.type)
        self.person.leg = "%s的脚" % self.type

# 指挥者
class PersonDirector(object):
    def __init__(self, pb=None):
        self.pb = pb

    def CreatePereson(self):
        self.pb.BuildHead()
        self.pb.BuildBody()
        self.pb.BuildArm()
        self.pb.BuildLeg()
        return self.pb.person

if __name__ == '__main__':
    pb = PersonThinBuilder()
    pd = PersonDirector(pb)
    thin_person = pd.CreatePereson()
    print(thin_person)

推荐阅读