sjms-2 创建型模式
设计模式分类
创建型模式(5种):工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式
结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式
创建型模式
简单工厂模式
内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。
角色:
工厂角色(Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta):
# abstract class
@abstractmethod
def pay(self, money):
pass class 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) # client
pf = PaymentFactory()
p = pf.create_payment('huabei')
p.pay(100) 隐藏了内部实现。把好几种支付方式的创建细节封装到工厂里面
优点:
隐藏了对象创建的实现细节
客户端不需要修改代码
缺点:
违反了单一职责原则,将创建逻辑几种到一个工厂类里
当添加新产品时,需要修改工厂类代码,违反了开闭原则
添加新的支付方式,需要去修改工厂函数。
工厂方法模式
内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。
角色:
抽象工厂角色(Creator)
具体工厂角色(Concrete Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta):
# abstract class
@abstractmethod
def pay(self, money):
pass class 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):
pass class 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() # client pf = 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):
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()
优点:
将客户端与类的具体实现相分离
每个工厂创建了一个完整的产品系列,使得易于交换产品系列
有利于产品的一致性(即产品之间的约束关系)
缺点:
难以支持新种类的(抽象)产品
如要增加手机产品配件,不再是3个一套,而是更多,就需要大改 。用的较少
建造者模式
内容:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
角色:
抽象建造者(Builder)
具体建造者(Concrete Builder)
指挥者(Director)
产品(Product)
from abc import ABCMeta, abstractmethod class 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):
pass class 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 # client builder = 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._instance class MyClass(Singleton):
def __init__(self, a):
self.a = a a = MyClass(10)
b = MyClass(20) print(a.a)
print(b.a)
print(id(a), id(b)) """
20
20
1319845376968 1319845376968
""" # 日志对象
# 数据库链接池
创建型模式小结
抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更灵活也更复杂。
通常情况下、设计以简单工厂模式或工厂方法模式开始,当你发现设计需要更大的灵活性时,则像更复杂的设计模式演化。
sjms-2 创建型模式的更多相关文章
- 工厂方法模式——创建型模式02
1. 简单工厂模式 在介绍工厂方法模式之前,先介绍一下简单工厂模式.虽然简单工厂模式不属于GoF 23种设计模式,但通常将它作为学习其他工厂模式的入门,并且在实际开发中使用的也较为频繁. (1 ...
- 单例模式——创建型模式01
1. 名称 单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类.单例模式是一种对象创建型模式. 2. 问题 ...
- C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)
一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配 ...
- Java设计模式之创建型模式
创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类
- 第26章 创建型模式大PK
26.1 工厂方法模式 VS 建造者模式 26.1.1 按工厂方法建造超人 (1)产品:两类超人,成年超人和未成年超人. (2)工厂:这里选择简单工厂 [编程实验]工厂方法建造超人 //创建型模式大P ...
- 创建型模式(前引)简单工厂模式Simple Factory
一引出的原因(解决下面的问题) 简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式. 在简单工厂模式 ...
- 设计模式之美:Creational Patterns(创建型模式)
创建型模式(Creational Patterns)抽象了对象实例化过程. 它们帮助一个系统独立于如何创建.组合和表示它的那些对象. 一个类创建型模式使用继承改变被实例化的类. 一个对象创建型模式将实 ...
- 设计模式学习之建造者模式(Builder,创建型模式)(6)
假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...
- 设计模式学习之原型模式(Prototype,创建型模式)(5)
通过序列化的方式实现深拷贝 [Serializable] public class Person:ICloneable { public string Name { get; set; } publi ...
- 设计模式学习之单例模式(Singleton,创建型模式)(4)
假如程序中有一个Person类,我的需求就是需要在整个应用程序中只能new一个Person,而且这个Person实例在应用程序中进行共享,那么我们该如何实现呢? 第一步: 新建一个Person类,类中 ...
随机推荐
- redis多实例和高可用
实验:多实例节点 10.220.5.65(三个实例) 高可用节点:10.220.5.67 创建目录,将三个实例文件都放在这个目录中 [root@ ~]# yum install redis -y [r ...
- 50代码HTML5 Canvas 3D 编辑器优雅搞定
1024程序员节刚过,手痒想实现一个html的3d编辑器,看了three.js 同时还看了网上流传已久的<<基于 HTML5 Canvas 的简易 2D 3D 编辑器>>,都觉 ...
- python day03笔记总结
2019.3.29 S21 day03笔记总结 昨日回顾及补充 1.运算符补充 in not in 2.优先级 运算符与运算符之间也有优先级之分 今日内容 一.整型(int) py2 与 py3 的区 ...
- Selenium+Java的TestNG测试报告优化
本博主很懒,但学习很勤快,一般能从博客园直接转载的东西,本博主绝不动手写,无奈Selenium+java生成的测试报告在百度上搜索..反正我是没有看到.后来才知道TestNG它可以自动生成测试报告,但 ...
- MySql数据库命令行操作说明
MySql数据库操作说明 1. 使用电脑的运行cmd指令打开dos界面 2. 输入cd C:\Program Files\MySql\bin命令回车,进入mysqld目录 3. 输入mysql ...
- 转-CVE-2016-10190浅析-FFmpeg堆溢出漏洞
本文转载自CVE-2016-10190 FFmpeg Heap Overflow 漏洞分析及利用 前言 FFmpeg是一个著名的处理音视频的开源项目,使用者众多.2016年末paulcher发现FFm ...
- 【转】使用python实现appium的屏幕滑动
前些日子写一个滑动手机页面的小脚本,看到大家给的内容都是swipe方法,这里对swipe方法做一个小介绍: Swipe(int start x,int start y,int end x,int y, ...
- 古韵之乞巧 题解 dp题
[noip模拟赛1]古韵之乞巧 描述 闺女求天女,更阑意未阑. 玉庭开粉席,罗袖捧金盘. 向月穿针易,临风整线难. 不知谁得巧,明旦试相看. ——祖咏<七夕> 女子乞巧,是七夕的重头戏 ...
- vba多条件查询更新EXCEL数据导access数据库
功能:根据项目号和步骤ID,更新指定步骤完成时间.这里里边要匹配两个条件一个是项目ID “”projectID“” 另一个是 “”StepID“” 步骤ID. Sub SaveFini() Dim r ...
- vue项目跳转到外部链接
vue项目中遇到一个打印的功能.思考之后决定点击按钮,跳转到一个HTML页面(后台写的),利用window.print()方法调用浏览器的打印的功能. 所以,现在的问题是,怎样跳转到外部链接.开发vu ...