常见的设计模式-创作型模式

常见的设计模式-创作型模式

个人理解面向对象

从对象的角度去处理事情

一个做饭的例子:

比如要做一道好吃的鱼香肉丝。我们脑子里想到的是洗、切、炒之类的具体步骤就是面相过程思维

若是想到先用刀然后拿锅炒菜就是面相对象思维

设计模式是干什么的

设计模式的目的是更好的组织你的代码

创建型模式

创建型模式提供了创建对象的机制, 能够提升已有代码的灵活性和可复用性。

工厂方法

工厂模式使用特殊的方法来代替原本类中的构造函数的使用

比如需要初始化一个sqlalchemy连接但是根据业务的不同要能个连接到不同的


\#产品 class Mysql(object): """mysql对象 """ def __repr__(self): connectstr = "" return connectstr class sqlserver(object): """sqlserver对象 """ def __repr__(self): connectstr = "" return connectstr import abc class AbstractFactory(object): """创建者 """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def product_engine(self): pass #具体创建者 class MysqlFactory(AbstractFactory): """mysql工厂 """ def product_engine(self): return Mysql() class sqlserverFactory(AbstractFactory): """sqlserver工厂 """ def product_engine(self): return sqlserver() c1 = MysqlFactory().product_engine() c2 = sqlserverFactory().product_engine()

抽象工厂

简单来说上面提到的类似于xx食品工厂,或者xx 物流公司。那么更加笼统(抽象)的说法那这些就是工厂或者公司

由抽象工厂来 组织和创建工厂
抽象工厂模式与工厂方法模式最大的区别在于,抽象工厂中的一个工厂对象可以负责多个不同产品对象的创建 ,这样比工厂方法模式更为简单、有效率

工厂继承抽象工厂。在抽象工厂里丰富方法实现生产多种产品

生成器

当你需要创建一个可能有许多配置选项的对象时, 该模式会特别有用。
类似与一个装配流水线

使用生成器的方式去实现一个类的初始化可以将一个复杂类的初始化进行解耦。

分割初始化

延迟创建

通过一个生成器对象去创建对象

from __future__ import annotations
from abc import ABC, abstractmethod, abstractproperty
from typing import Any


class Builder(ABC):
    """
    The Builder interface specifies methods for creating the different parts of
    the Product objects.
    """

    @abstractproperty
    def product(self) -> None:
        pass

    @abstractmethod
    def produce_part_a(self) -> None:
        pass

    @abstractmethod
    def produce_part_b(self) -> None:
        pass

    @abstractmethod
    def produce_part_c(self) -> None:
        pass


class ConcreteBuilder1(Builder):
    """
    The Concrete Builder classes follow the Builder interface and provide
    specific implementations of the building steps. Your program may have
    several variations of Builders, implemented differently.
    """

    def __init__(self) -> None:
        """
        A fresh builder instance should contain a blank product object, which is
        used in further assembly.
        """
        self.reset()

    def reset(self) -> None:
        self._product = Product1()

    @property
    def product(self) -> Product1:
        """
        Concrete Builders are supposed to provide their own methods for
        retrieving results. That's because various types of builders may create
        entirely different products that don't follow the same interface.
        Therefore, such methods cannot be declared in the base Builder interface
        (at least in a statically typed programming language).

        Usually, after returning the end result to the client, a builder
        instance is expected to be ready to start producing another product.
        That's why it's a usual practice to call the reset method at the end of
        the `getProduct` method body. However, this behavior is not mandatory,
        and you can make your builders wait for an explicit reset call from the
        client code before disposing of the previous result.
        """
        product = self._product
        self.reset()
        return product

    def produce_part_a(self) -> None:
        self._product.add("PartA1")

    def produce_part_b(self) -> None:
        self._product.add("PartB1")

    def produce_part_c(self) -> None:
        self._product.add("PartC1")


class Product1():
    """
    It makes sense to use the Builder pattern only when your products are quite
    complex and require extensive configuration.

    Unlike in other creational patterns, different concrete builders can produce
    unrelated products. In other words, results of various builders may not
    always follow the same interface.
    """

    def __init__(self) -> None:
        self.parts = []

    def add(self, part: Any) -> None:
        self.parts.append(part)

    def list_parts(self) -> None:
        print(f"Product parts: {', '.join(self.parts)}", end="")


class Director:
    """
    The Director is only responsible for executing the building steps in a
    particular sequence. It is helpful when producing products according to a
    specific order or configuration. Strictly speaking, the Director class is
    optional, since the client can control builders directly.
    """

    def __init__(self) -> None:
        self._builder = None

    @property
    def builder(self) -> Builder:
        return self._builder

    @builder.setter
    def builder(self, builder: Builder) -> None:
        """
        The Director works with any builder instance that the client code passes
        to it. This way, the client code may alter the final type of the newly
        assembled product.
        """
        self._builder = builder

    """
    The Director can construct several product variations using the same
    building steps.
    """

    def build_minimal_viable_product(self) -> None:
        self.builder.produce_part_a()

    def build_full_featured_product(self) -> None:
        self.builder.produce_part_a()
        self.builder.produce_part_b()
        self.builder.produce_part_c()


if __name__ == "__main__":
    """
    The client code creates a builder object, passes it to the director and then
    initiates the construction process. The end result is retrieved from the
    builder object.
    """

    director = Director()
    builder = ConcreteBuilder1()
    director.builder = builder

    print("Standard basic product: ")
    director.build_minimal_viable_product()
    builder.product.list_parts()

    print("\n")

    print("Standard full featured product: ")
    director.build_full_featured_product()
    builder.product.list_parts()

    print("\n")

    # Remember, the Builder pattern can be used without a Director class.
    print("Custom product: ")
    builder.produce_part_a()
    builder.produce_part_b()
    builder.product.list_parts()

原型

原型模式就是完完整的复制一份一摸一样的对象。不用通过init去初始化一个对象再去改变属性

可以应用的场景比如我有一份公共的配置文件。但是由于python可变数据类型 直接通过赋值会污染原始变量。可以通过copy复制一份对象。

import copy
a = [1,2,3,[4,5],6]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
b.append(10)
c[3].append(11)
d[3].append(12)
print(a) # [1,2,3,[4,5,11],6,11]
print(b) # 同a
print(c) # [1,2,3,[4,5,11],6]
print(d) # [1,2,3,[4,5,12],6]

单例

当你想要希望创建的类只能创建一个对象。比如之创建一个资源连接。或者访问一文件。一个摄像头

通过创建一个类的对象然后全局导入使用这个对象

class Singleton(object):
    def foo(self):
        pass
singleton = Singleton()

通过类方式创建

class SingletonMeta(type):
    """
    The Singleton class can be implemented in different ways in Python. Some
    possible methods include: base class, decorator, metaclass. We will use the
    metaclass because it is best suited for this purpose.
    """

    _instances = {}

    def __call__(cls, *args, **kwargs):
        """
        Possible changes to the value of the `__init__` argument do not affect
        the returned instance.
        """
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]


class Singleton(metaclass=SingletonMeta):
    #手动制定你的元类是谁
    def some_business_logic(self):
        """
        Finally, any singleton should define some business logic, which can be
        executed on its instance.
        """

        # ...


if __name__ == "__main__":
    # The client code.

    s1 = Singleton()
    s2 = Singleton()

    if id(s1) == id(s2):
        print("Singleton works, both variables contain the same instance.")
    else:
        print("Singleton failed, variables contain different instances.")

发表评论

电子邮件地址不会被公开。 必填项已用*标注