博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
sjms-2 创建型模式
阅读量:6160 次
发布时间:2019-06-21

本文共 7554 字,大约阅读时间需要 25 分钟。

设计模式分类

创建型模式(5种):工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式

结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式

创建型模式

简单工厂模式

内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。

角色:
工厂角色(Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)

 

from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):    # abstract class    @abstractmethod    def pay(self, money):        passclass Alipay(Payment):    def __init__(self, use_huabei=False):        self.use_huaei = use_huabei    def pay(self, money):        if self.use_huaei:            print("花呗支付%d元." % money)        else:            print("支付宝余额支付%d元." % money)class WechatPay(Payment):    def pay(self, money):        print("微信支付%d元." % money)class PaymentFactory:    def create_payment(self, method):        if method == 'alipay':            return Alipay()        elif method == 'wechat':            return WechatPay()        elif method == 'huabei':            return Alipay(use_huabei=True)        else:            raise TypeError("No such payment named %s" % method)# clientpf = PaymentFactory()p = pf.create_payment('huabei')p.pay(100) 隐藏了内部实现。把好几种支付方式的创建细节封装到工厂里面

优点:

隐藏了对象创建的实现细节
客户端不需要修改代码
缺点:
违反了单一职责原则,将创建逻辑几种到一个工厂类里
当添加新产品时,需要修改工厂类代码,违反了开闭原则

 

添加新的支付方式,需要去修改工厂函数。

工厂方法模式

内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。

角色:
抽象工厂角色(Creator)
具体工厂角色(Concrete Creator)
抽象产品角色(Product)        
具体产品角色(Concrete Product)   

from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):    # abstract class    @abstractmethod    def pay(self, money):        passclass Alipay(Payment):    def __init__(self, use_huabei=False):        self.use_huaei = use_huabei    def pay(self, money):        if self.use_huaei:            print("花呗支付%d元." % money)        else:            print("支付宝余额支付%d元." % money)class WechatPay(Payment):    def pay(self, money):        print("微信支付%d元." % money)class BankPay(Payment):    def pay(self, money):        print("银行卡支付%d元." % money)# ===class PaymentFactory(metaclass=ABCMeta):  # 类似作用桥梁    @abstractmethod    def create_payment(self):        passclass AlipayFactory(PaymentFactory):    def create_payment(self):        return Alipay()class WechatPayFactory(PaymentFactory):    def create_payment(self):        return WechatPay()class HuabeiFactory(PaymentFactory):    def create_payment(self):        return Alipay(use_huabei=True)class BankPayFactory(PaymentFactory):    def create_payment(self):        return BankPay()# clientpf = HuabeiFactory()p = pf.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):        passclass CPU(metaclass=ABCMeta):    @abstractmethod    def show_cpu(self):        passclass 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()

  

优点:

将客户端与类的具体实现相分离
每个工厂创建了一个完整的产品系列,使得易于交换产品系列
有利于产品的一致性(即产品之间的约束关系)
缺点:
难以支持新种类的(抽象)产品

 

如要增加手机产品配件,不再是3个一套,而是更多,就需要大改 。用的较少

 

建造者模式 

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

角色:
抽象建造者(Builder)
具体建造者(Concrete Builder)
指挥者(Director)
产品(Product)

 

from abc import ABCMeta, abstractmethodclass Player:    def __init__(self, face=None, body=None, arm=None, leg=None):        self.face = face        self.body = body        self.arm = arm        self.leg = leg    def __str__(self):        return "%s, %s, %s, %s" % (self.face, self.body, self.arm, self.leg)class PlayerBuilder(metaclass=ABCMeta):    @abstractmethod    def build_face(self):        pass    @abstractmethod    def build_body(self):        pass    @abstractmethod    def build_arm(self):        pass    @abstractmethod    def build_leg(self):        passclass SexyGirlBuilder(PlayerBuilder):    def __init__(self):        self.player = Player()    def build_face(self):        self.player.face = "漂亮脸蛋"    def build_body(self):        self.player.body = "苗条"    def build_arm(self):        self.player.arm = "漂亮胳膊"    def build_leg(self):        self.player.leg = "大长腿"class MonsterBuilder(PlayerBuilder):    def __init__(self):        self.player = Player()    def build_face(self):        self.player.face = "怪兽脸"    def build_body(self):        self.player.body = "怪兽身材"    def build_arm(self):        self.player.arm = "长毛的胳膊"    def build_leg(self):        self.player.leg = "长毛的腿"class PlayerDirector: # 控制组装顺序    def build_player(self, builder):        builder.build_body()        builder.build_face()        builder.build_arm()        builder.build_leg()        return builder.player# clientbuilder = MonsterBuilder()director = PlayerDirector()p = director.build_player(builder)print(p)

  

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

优点:
隐藏了一个产品的内部结构和装配过程
将构造代码与表示代码分开
可以对构造过程进行更精细的控制

单例模式

内容:保证一个类只有一个实例,并提供一个访问它的全局访问点。

角色:
单例(Singleton)
优点:
对唯一实例的受控访问
单例相当于全局变量,但防止了命名空间被污染

class Singleton:    def __new__(cls, *args, **kwargs):        _instance = None  # 假定没有实列        if not hasattr(cls, "_instance"): # 如果没有就创建,有就返回实列            cls._instance = super(Singleton, cls).__new__(cls)        return cls._instanceclass MyClass(Singleton):    def __init__(self, a):        self.a = aa = MyClass(10)b = MyClass(20)print(a.a)print(b.a)print(id(a), id(b))"""20201319845376968 1319845376968      """# 日志对象# 数据库链接池

  

创建型模式小结

抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更灵活也更复杂。
通常情况下、设计以简单工厂模式或工厂方法模式开始,当你发现设计需要更大的灵活性时,则像更复杂的设计模式演化。

 

转载于:https://www.cnblogs.com/wenyule/p/10534262.html

你可能感兴趣的文章
简洁优雅地实现夜间模式
查看>>
react学习总结
查看>>
在soapui上踩过的坑
查看>>
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>
Apache通过mod_php5支持PHP
查看>>
java学习:jdbc连接示例
查看>>
Silverlight 如何手动打包xap
查看>>
禁用ViewState
查看>>
Android图片压缩(质量压缩和尺寸压缩)
查看>>
nilfs (a continuent snapshot file system) used with PostgreSQL
查看>>
【SICP练习】150 练习4.6
查看>>
HTTP缓存应用
查看>>
KubeEdge向左,K3S向右
查看>>
DTCC2013:基于网络监听数据库安全审计
查看>>
CCNA考试要点大搜集(二)
查看>>
ajax查询数据库时数据无法更新的问题
查看>>
Kickstart 无人职守安装,终于搞定了。
查看>>