设计模式-创建模式型
简单工厂模式
# 一个工厂管多件产品
""" 内容: 不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。 角色: 工厂角色(Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) """ # 优缺点: """ 优点 隐藏了对象创建的实现细节 客户端不需要修改代码 缺点: 违反了单一职责原则,将创建逻辑几种到一个工厂类里 当添加新产品时,需要修改工厂类代码,违反了开闭原则 """
代码实现
from abc import abstractmethod, ABCMeta class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): raise NotImplementedError class Alipay(Payment): def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): if self.use_huabei: print("花呗支付%s元" % money) else: print("支付宝支付%s元" % money) class ApplePay(Payment): def __init__(self): pass def pay(self, money): print("苹果支付%s元" % money) class PaymentFactory: # 隐藏对象创建的细节,客户端不序修改代码,相当于中间人 def create_payment(self, method): if method == "alipay": return Alipay() elif method == "applepay": return ApplePay() elif method == "huabei": return Alipay(use_huabei=True) else: raise NameError(method) # p = Alipay() factory = PaymentFactory() p = factory.create_payment("huabei") p.pay(100)
工厂方法模式
# 一个工厂管一件产品 # 内容: 定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。 # 角色: 抽象工厂角色(Creator) 接口 具体工厂角色(Concrete Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) 工厂方法模式相比简单工厂模式将每个具体产品都对应了一个具体工厂。 # 使用场景 需要生产多种、大量复杂对象的时候 需要降低耦合度的时候 当系统中的产品种类需要经常扩展的时候 # 优缺点 """ 优点: 每个具体产品都对应一个具体工厂类,不需要修改工厂类代码 隐藏了对象创建的实现细节 缺点: 每增加一个具体产品类,就必须增加一个相应的具体工厂类 """
代码实现
from abc import abstractmethod, ABCMeta class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class Alipay(Payment): def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): if self.use_huabei: print("花呗支付%s元" % money) else: print("支付宝支付%s元" % money) class ApplePay(Payment): def pay(self, money): print("苹果支付%s元" % money) class WechatPay(Payment): def pay(self, money): print("微信支付%s元" % money) class PaymentFactory(metaclass=ABCMeta): @abstractmethod def create_payment(self): pass class AlipayFactory(PaymentFactory): def create_payment(self): return Alipay() class ApplePayFactory(PaymentFactory): def create_payment(self): return ApplePay() class HuabeiFactory(PaymentFactory): def create_payment(self): return Alipay(use_huabei=True) class WechatFactory(PaymentFactory): def create_payment(self): return WechatPay() factory = HuabeiFactory() p = factory.create_payment() p.pay(100)
抽象工厂模式
# 相比工厂方法模式,每个抽象工厂模式中的每个具体工厂都生产一套产品。 """ 内容: 定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。 例: 生产一部手机,需要手机壳、CPU、操作系统三类对象进行组装,其中每类对象都有不同的种类。对每个具体工厂,分别生产一部手机所需要的三个对象。 角色: 抽象工厂角色(Creator) 具体工厂角色(Concrete Creator) 抽象产品角色(Product) 具体产品角色(Concrete Product) 客户端(Client) 相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。 """ # 适用场景 """ 系统要独立于产品的创建与组合时 强调一系列相关的产品对象的设计以便进行联合使用时 提供一个产品类库,想隐藏产品的具体实现时 """ # 优缺点 """ 优点: 将客户端与类的具体实现相分离 每个工厂创建了一个完整的产品系列,使得易于交换产品系列 有利于产品的一致性(即产品之间的约束关系) 缺点: 难以支持新种类的(抽象)产品 """
代码实现
from abc import abstractmethod, ABCMeta # ------抽象产品------ class PhoneShell(metaclass=ABCMeta): @abstractmethod def show_shell(self): pass class CPU(metaclass=ABCMeta): @abstractmethod def show_cpu(self): pass class OS(metaclass=ABCMeta): @abstractmethod def show_os(self): pass # ------抽象工厂------ class PhoneFactory(metaclass=ABCMeta): @abstractmethod def make_shell(self): pass @abstractmethod def make_cpu(self): pass @abstractmethod def make_os(self): pass # ------具体产品------ class SmallShell(PhoneShell): def show_shell(self): print("普通手机小手机壳") class BigShell(PhoneShell): def show_shell(self): print("普通手机大手机壳") class AppleShell(PhoneShell): def show_shell(self): print("苹果手机壳") class SnapDragonCPU(CPU): def show_cpu(self): print("骁龙CPU") class MediaTekCPU(CPU): def show_cpu(self): print("联发科CPU") class AppleCPU(CPU): def show_cpu(self): print("苹果CPU") class Android(OS): def show_os(self): print("Android系统") class IOS(OS): def show_os(self): print("iOS系统") # ------具体工厂------ class MiFactory(PhoneFactory): def make_cpu(self): return SnapDragonCPU() def make_os(self): return Android() def make_shell(self): return BigShell() class HuaweiFactory(PhoneFactory): def make_cpu(self): return MediaTekCPU() def make_os(self): return Android() def make_shell(self): return SmallShell() class IPhoneFactory(PhoneFactory): def make_cpu(self): return AppleCPU() def make_os(self): return IOS() def make_shell(self): return AppleShell() # ------客户端------ class Phone: def __init__(self, cpu, os, shell): self.cpu = cpu self.os = os self.shell = shell def show_info(self): print("手机信息:") self.cpu.show_cpu() self.os.show_os() self.shell.show_shell() def make_phone(factory): cpu = factory.make_cpu() os = factory.make_os() shell = factory.make_shell() return Phone(cpu, os, shell) p1 = make_phone(IPhoneFactory()) p1.show_info()
建造者模式
# 建造者模式与抽象工厂模式相似,也用来创建复杂对象。着重构造顺序 """ 内容: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 角色: 抽象建造者(Builder) 具体建造者(Concrete Builder) 指挥者(Director) 产品(Product) 建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别是建造者模式着重一步步构造一个复杂对象, 而抽象工厂模式着重于多个系列的产品对象。 """ # 适用场景 """ 当创建复杂对象的算法(Director)应该独立于该对象的组成部分以及它们的装配方式(Builder)时 当构造过程允许被构造的对象有不同的表示时(不同Builder)。 """ # 优缺点 """ 优点 隐藏了一个产品的内部结构和装配过程 将构造代码与表示代码分开 可以对构造过程进行更精细的控制 """
代码实现
from abc import abstractmethod, ABCMeta # ------产品------ class Player: def __init__(self, face=None, body=None, arm=None, leg=None): self.face = face self.arm = arm self.leg = leg self.body = body def __str__(self): return "%s, %s, %s, %s" % (self.face, self.arm, self.body, self.leg) # ------建造者------ class PlayerBuilder(metaclass=ABCMeta): @abstractmethod def build_face(self): pass @abstractmethod def build_arm(self): pass @abstractmethod def build_leg(self): pass @abstractmethod def build_body(self): pass @abstractmethod def get_player(self): pass class BeautifulWomanBuilder(PlayerBuilder): def __init__(self): self.player = Player() def build_face(self): self.player.face = "漂亮脸蛋" def build_arm(self): self.player.arm = "细胳膊" def build_body(self): self.player.body = "细腰" def build_leg(self): self.player.leg = "长腿" def get_player(self): return self.player class PlayerDirector: # 控制顺序 def build_player(self, builder): builder.build_body() builder.build_face() builder.build_arm() builder.build_leg() return builder.get_player() pd = PlayerDirector() pb = BeautifulWomanBuilder() p = pd.build_player(pb) print(p)
单例模式
# 内容: 保证一个类只有一个实例,并提供一个访问它的全局访问点。 # 角色: 单例(Singleton) # 适用场景 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时 文件系统 数据库连接对象 日志对象 # 优点: 对唯一实例的受控访问 单例相当于全局变量,但防止了命名空间被污染 # 与单例模式功能相似的概念: 全局变量、静态变量(方法)
实例
class Singleton(object): def __new__(cls,*args,**kwargs): if not hasattr(cls,"_instance"): cls._instance=super(Singleton,cls).__new__(cls) return cls._instance class Myclass(Singleton): def __init__(self,name=None): if name is not None: self.name=name a = MyClass("a") print(a) print(a.name) b = MyClass("b") print(b) print(b.name) print(a) print(a.name)
小结
使用抽象工厂模式,prototype(原型模式)或者建造者模式的设计甚至比使用工厂方法模式的那些设计更灵活,但他们也更加复杂。通常,设计以使用工厂方法模式开始,当设计者发现需要更大的灵活性时,设计便会向其他创建模式演化。当你在设计标准之间进行权衡的时候,了解多个模式可以给你提供更多的选择余地
依赖于继承的创建型模式:
工厂方法模式
依赖于组合的创建性模式:
抽象工厂模式、创建者模式
1