目录

  • 一、工厂模式
  • 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 类图

python设置一个类用于动态属性 python设计一个类_python设置一个类用于动态属性

  • 角色
  • 工厂类(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 类图

python设置一个类用于动态属性 python设计一个类_python_02

  • 角色:
  • 抽象工厂角色:拆分了工厂类
  • 具体工厂角色:对应了简单工厂模式的每个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 类图

python设置一个类用于动态属性 python设计一个类_类图_03

  • 角色
  • 抽象产品角色
  • 具体产品角色:可扩展
  • 抽象工厂角色:定义生产每个系列产品的方法
  • 具体工厂角色: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 类图

python设置一个类用于动态属性 python设计一个类_python_04

  • 角色
  • 构建类的管理类(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 类图

python设置一个类用于动态属性 python设计一个类_python设置一个类用于动态属性_05

  • 角色:只有一个类,类中只有一个方法,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 类图

python设置一个类用于动态属性 python设计一个类_类图_06

  • 角色
  • 克隆基类(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>