目录
- 一、工厂模式
- 1.1 简单工厂模式
- 1.1.1 概述
- 1.1.2 类图
- 1.1.3 实现
- 1.2 工厂方法模式
- 1.2.1 概述
- 1.2.2 类图
- 1.2.3 实现
- 1.3 抽象工厂模式
- 1.3.1 概述
- 1.3.2 类图
- 1.3.3 实现
- 二、建造者模式
- 2.1 概述
- 2.2 类图
- 2.3 实现
- 三、单例模式
- 3.1 概述
- 3.2 类图
- 3.3 实现
- 3.3.1 装饰器实现
- 3.3.2 new方法实现
- 3.3.3 模块实现
- 四、原型模式
- 4.1 概述
- 4.2 类图
- 4.3 实现
一、工厂模式
- 功能:创建对象的细节(若有大量的参数创建时需传入),对客户端保密,通过一个工厂类(其中写死参数)来负责创建实例
1.1 简单工厂模式
1.1.1 概述
- 定义:定义一个创建对象(实例化对象)的接口,通过参数来决定创建哪个类的实例
- 设计要点:此模式不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑,不符合“开放封闭”原则
- 适用场景:产品具有明显的继承关系,且产品的类型不太多;所有的产品具有相同的方法和类似的属性
1.1.2 类图
- 角色
- 工厂类(SimpleFactory):负责创建对象
- 抽象产品角色(Product)
- 具体产品角色:继承抽象产品角色,具体的产品类型
1.1.3 实现
- 代码示例
from abc import ABCMeta, abstractmethod
########################################################
# 基类:抽象产品角色
class Product(metaclass=ABCMeta):
@abstractmethod
def show_price(self, price):
pass
# 派生类:具体产品角色,以下这两个都是
class Football(Product):
def show_price(self, price):
print("足球的实时价钱为%d元" % price)
class Basketball(Product):
def show_price(self, price):
print("篮球的实时价钱为%d元" % price)
########################################################
# 工厂类
class Factory:
def create_product(self, name):
if name == "football":
# 优势:在这里可以写死参数,对客户端隐藏参数细节
return Football()
elif name == "basketball":
return Basketball()
# 在这里可以继续扩展,加一个具体产品角色,这里就要加一条语句
else:
raise TypeError("No such product named %s." % name)
########################################################
if __name__ == "__main__":
# 客户端调用
p = Factory()
prod = p.create_product("football")
prod.show_price(35)
>>> 足球的实时价钱为35元
1.2 工厂方法模式
1.2.1 概述
- 定义:定义一个实例化对象的接口,让子类决定创建哪个类的实例,工厂方法使一个类的实例化延迟到其子类
- 特点:改进简单工厂模式,使其符合“开放-封闭”原则
- 优点:每个类职责明确,一个工厂对应一个产品
- 缺点:每增加一个具体产品类,就增加一个相应的具体工厂类
1.2.2 类图
- 角色:
- 抽象工厂角色:拆分了工厂类
- 具体工厂角色:对应了简单工厂模式的每个if…else…
- 抽象产品角色:与简单工厂模式相同
- 具体产品角色:与简单工厂模式相同
1.2.3 实现
- 代码示例
from abc import ABCMeta, abstractmethod
############################################
# 基类:抽象产品角色
class Product(metaclass=ABCMeta):
@abstractmethod
def show_price(self, price):
pass
# 派生类:具体产品角色,以下这两个都是
class Football(Product):
def show_price(self, price):
print("足球的实时价钱为%d元" % price)
class Basketball(Product):
def show_price(self, price):
print("篮球的实时价钱为%d元" % price)
############################################
# 与简单工厂模式差别:此处以单一职责模式扩展了工厂类
# 基类:抽象工厂角色
class Factory(metaclass=ABCMeta):
@abstractmethod
def create_product(self):
pass
# 派生类:具体工厂角色
class FootballFactory(Factory):
def create_product(self):
# 此处可以设置传入参数
return Football()
class BasketballFactory(Factory):
def create_product(self):
return Basketball()
############################################
if __name__ == "__main__":
# 客户端调用:直接调用生成对应商品的工厂
p = FootballFactory()
prod = p.create_product()
prod.show_price(35)
>>> 足球的实时价钱为35元
1.3 抽象工厂模式
1.3.1 概述
- 定义:提供一个创建一系列相关或相互依赖的对象的接口,而无须指定它们的具体类
- 特点
- 优点:不仅可以封装创建对象的细节,还可以限定一些列类的组合使用
- 缺点:过于繁琐,较少用了,多于三级就很臃肿了,功能类似建造者模式,此模式关注创建多谢
1.3.2 类图
- 角色
- 抽象产品角色
- 具体产品角色:可扩展
- 抽象工厂角色:定义生产每个系列产品的方法
- 具体工厂角色:Factory1和Factory2分别生产子分类1的每一系列产品和子分类2的每一系列产品
1.3.3 实现
- 代码示例
from abc import ABCMeta, abstractmethod
##################################
# 抽象产品
# 手机壳
class Shell(metaclass=ABCMeta):
@abstractmethod
def select_shell(self):
pass
# CPU处理器
class CPU(metaclass=ABCMeta):
@abstractmethod
def select_cpu(self):
pass
##################################
# 具体产品
class MiShell(Shell):
def select_shell(self):
print("小米手机壳")
class IPhoneShell(Shell):
def select_shell(self):
print("苹果手机壳")
class MiCPU(CPU):
def select_cpu(self):
print("小米CPU")
class IPhoneCPU(CPU):
def select_cpu(self):
print("苹果CPU")
##################################
# 抽象工厂
class CreatePhone(metaclass=ABCMeta):
@abstractmethod
def make_shell(self):
pass
@abstractmethod
def make_cpu(self):
pass
##################################
# a 具体工厂:主语句的第一个创建的产品系列工厂,
# 里面可以制造一系列此产品的对应部件
class CreateMi(CreatePhone):
def make_shell(self):
return MiShell()
def make_cpu(self):
return MiCPU()
class CreateIPhone(CreatePhone):
def make_shell(self):
return IPhoneShell()
def make_cpu(self):
return IPhoneCPU()
##################################
# 客户端
# c、封装的phone类
class Phone:
def __init__(self, shell, cpu, os):
self.shell = shell
self.cpu = cpu
def show_info(self):
print("手机信息:")
self.shell.select_shell()
self.cpu.select_cpu()
# b 传入具体工厂对象:factory 从a 类获得
def make_phone(factory):
# 以下方法都是a类的方法
shell = factory.make_shell()
cpu = factory.make_cpu()
# 返回客户端封装的pyhone类 , 对应c
return Phone(shell, cpu, os)
############################################
if __name__ == "__main__":
# 客户端调用:此处模式即指定了具体产品的各个组合类,对应 a
phone_type = CreateMi()
# 调用上一步生成的各个组合类,进行phone的组装,对应 b
phone = make_phone(phone_type)
phone.show_info()
>>>手机信息:
>>>小米手机壳
>>>小米CPU
二、建造者模式
2.1 概述
- 定义:将一个复杂对象的构建与表示分离,同样的构建过程可以创建不同的表现
- 设计要点:
- 组合与建造者关系:前者关注的是对象内部的组成结构,强调的是部分与整体的关系。后者关注的是对象的创建过程,即由一个一个的子部件构建一个成品的过程
- 创建类:增加了很多创建类,如果产品的类型和种类比较多,将会增加很多类,使系统庞杂
- 适用场景:如XML
- 过程复杂:产品(对象)的创建过程比较复杂
- 内部结构类似:产品有很多种类,每个种类之间内部结构比较类似
2.2 类图
- 角色
- 构建类的管理类(BuilderManager):也叫导演类,负责管理每一种产品的创建数量和创建顺序
- 抽象构建类(Builder):具体构建类(ProductABuilder、ProductBBuilder)
- 抽象产品类(Product):具体的产品类型(ProductA、ProductB)
2.3 实现
- 代码示例
from abc import ABCMeta, abstractmethod
############################################
# 产品
class Player:
def __init__(self, face=None, body=None):
self.face = face
self.body = body
def __str__(self):
return "%s %s" % (self.face, self.body)
############################################
# 抽象建造者
class PlayerBuilder(metaclass=ABCMeta):
@abstractmethod
def build_face(self):
pass
@abstractmethod
def build_body(self):
pass
############################################
# 具体建造者
class Beauty(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "漂亮脸蛋"
def build_body(self):
self.player.body = "漂亮身材"
class Monster(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "怪兽脸蛋"
def build_body(self):
self.player.body = "怪兽身材"
############################################
# 导演
class PlayerDirector:
def create_player(self, builder):
builder.build_body()
builder.build_face()
return builder.player
############################################
if __name__ == "__main__":
# 客户端调用:首句可以改成Beauty,其他都不变,即可切换构建对象
builder = Monster()
director = PlayerDirector()
# 这句是核心:导演创建对象(传入建造者对象)
p = director.create_player(builder)
print(p)
>>> 怪兽脸蛋 怪兽身材
三、单例模式
3.1 概述
- 定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点,避免重复创建实例,以节省系统资源
- 适用场景:类只有一个且只能有一个实例,如全局管理类(Manager)
- 设计要点:常用装饰器方式实现
3.2 类图
- 角色:只有一个类,类中只有一个方法,getInstance
3.3 实现
3.3.1 装饰器实现
- 代码示例(推荐)
def singleton(cls):
_instance = {}
def wrap(*args, **kwargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs)
return _instance[cls]
return wrap
# 此语法糖相当于MyClass = singleton(MyClass)
@singleton
class MyClass:
def __init__(self, num=0):
self.num = num
print("创建MyClass类对象")
if __name__ == "__main__":
a = MyClass(10)
b = MyClass(20)
c = MyClass()
print(a.num)
print(b.num)
print(c.num)
print(id(a), id(b), id(c))
# 输出结果:
# MyClass只创建了一个对象,后续b、c都没创建新对象
>>> 创建MyClass类对象
# 修改num值不能通过初始化类对象传入,只能写类方法修改
>>> 10
>>> 10
>>> 10
# a、b、c三者的地址相同,所以也佐证没创建新对象
>>> 140496911499376 140496911499376 140496911499376
3.3.2 new方法实现
- 代码示例
class Singleton(object):
def __init__(self, num=0):
if not hasattr(Singleton, "_first_init"):
print("__init__方法被调用")
Singleton._first_init = True
self.num = num
# new方法创建类实例,init方法添加属性
# hasattr方法判断类是否有属性
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
print("创建新实例")
Singleton._instance = object.__new__(cls)
return Singleton._instance
if __name__ == "__main__":
a = Singleton(10)
b = Singleton(20)
c = Singleton()
print(a.num)
print(b.num)
print(c.num)
print(id(a), id(b), id(c))
# new和init方法只调用了一次
>>> 创建新实例
>>> __init__方法被调用
>>> 10
>>> 10
>>> 10
>>> 140163278712944 140163278712944 140163278712944
特点:直接将单例模式写入类中,多线程也有应用
3.3.3 模块实现
- 简介:模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码
四、原型模式
4.1 概述
- 定义:用原型实例指定要创建对象的种类,并通过深拷贝这些原型的属性来创建新的对象,也叫克隆模式
- 适用场景:常用于深拷贝(深拷贝即同时拷贝引用类型对象及其指向的值),如果创建新对象如复杂对象成本较高(比new性能好),读写硬盘数据等操作
- 设计要点:区分深浅拷贝
4.2 类图
- 角色
- 克隆基类(Clone)
- 具体实现类
4.3 实现
- 代码示例
from copy import deepcopy
# 克隆模式的基类
class Clone:
# 深拷贝:递归拷贝对象的属性,及对象的指针
def clone(self):
return deepcopy(self)
# 实现类:继承父类的方法
class Person(Clone):
def __init__(self, name):
self.__name = name
def show_self(self):
print("我是" + self.__name)
if __name__ == "__main__":
person01 = Person("duke")
person02 = person01
person03 = person01.clone()
# person01和person02,指向相同的内存空间
print(person01)
print(person02)
# person03为深拷贝,指向不同的内存空间
print(person03)
###############################################
# 输出
>>> <__main__.Person object at 0x7fcdd74698e0>
>>> <__main__.Person object at 0x7fcdd74698e0>
>>> <__main__.Person object at 0x7fcdda008460>