美文网首页
python 抽象工厂实践+ 元类自动注册工厂类

python 抽象工厂实践+ 元类自动注册工厂类

作者: 逐风细雨 | 来源:发表于2021-10-22 13:42 被阅读0次

    抽象工厂定义

       提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

    适用性

    • 一个系统要独立于它的产品的创建、组合和表示时。

    • 一个系统要由多个产品系列中的一个来配置时。

    • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。

    • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。
      参考文章
      二十三种设计模式及其python实现

    缺点

       抽象工厂方法的一个弊端是,每次新增具体的业务类时,都需要在对于的工厂类中新增一个类型。

    改良

       因为元类是可以在声明类对象时,进行一些前置动作的,如果在类声明时,将整个类对象按类名:类对象存储在一个字典里面,工厂方法按类名获取到类对象,弥补需手动修改代码的缺点

    实践代码如下

    """
    A.实践 工厂模式 和抽象工厂模式
    场景 adb通过连接设备
    连接类型
    1. usb连接
    2. wifi连接
    设备类型
    3. 手机
    4. 平板
    B. 使用元类,自动注册工厂类
    """
    
    
    class ConnectionTypeError(Exception):
        pass
    
    
    class DeviceTypeError(Exception):
        pass
    
    
    class FactoryTypeError(Exception):
        pass
    
    
    class ConnectionStack:
        """
        存储连接对象
        """
        connection_map = dict()
    
        @classmethod
        def register(cls, name, obj):
            print(f"ConnectionStack 注册类对象{name}")
            cls.connection_map[name] = obj
    
        @classmethod
        def get_connection_cls(cls, name):
            return cls.connection_map.get(name)
    
    
    class DeviceStack:
        """
        存储设备类对象
        """
        device_map = dict()
    
        @classmethod
        def register(cls, name, obj):
            cls.device_map[name] = obj
            print(f"DeviceStack 注册类对象{name}")
    
        @classmethod
        def get_device_cls(cls, name):
            return cls.device_map.get(name)
    
    
    class ConnectionMete(type):
        """
        连接类的元类,
        1. 将类对象保存在ConnectionStack;
        2. 通过类名获取类对象  eg:ConnectionStack.get_connection_cls(class_name)
        """
    
        def __new__(cls, cls_name, cls_base, cls_dict):
            cls_obj = super(ConnectionMete, cls).__new__(cls, cls_name, cls_base, cls_dict)
            ConnectionStack.register(cls_name, cls_obj)
            return cls_obj
    
    
    class DeviceMete(type):
        """
        设备类的元类,
        1. 将类对象保存在 DeviceStack;
        2. 通过类名获取类对象  eg: DeviceStack.get_device_cls(class_name)
        """
    
        def __new__(cls, cls_name, cls_base, cls_dict):
            cls_obj = super(DeviceMete, cls).__new__(cls, cls_name, cls_base, cls_dict)
            DeviceStack.register(cls_name, cls_obj)
            return cls_obj
    
    
    class Connection(metaclass=ConnectionMete):
        """
        设备基类
        """
    
        def connect(self, connection_id):
            pass
    
        def disconnect(self, connection_id):
            pass
    
        def execute_cmd(self, cmd):
            pass
    
    
    class USBConnection(Connection):
        """
        工厂方法模式,每个连接都有一个独立的类
        """
    
        def connect(self, connection_id):
            print(f"设备【{connection_id}】通过usb建立连接")
    
    
    class WIFIConnection(Connection):
        """
        工厂方法模式,每个连接都有一个独立的类
        """
    
        def connect(self, connection_id):
            print(f"设备【{connection_id}】通过wifi建立连接")
    
    
    class ConnectionFactory:
        """
        工厂模式-返回连接对象实例
        """
    
        def create_connection(self, connection_cls_name):
            connection = ConnectionStack.get_connection_cls(connection_cls_name)
            if connection:
                return connection()
            else:
                raise ConnectionTypeError
    
    
    class Device(metaclass=DeviceMete):
    
        def boot_app(self, package_name):
            pass
    
    
    class Mobile(Device):
    
        def boot_app(self, package_name):
            print(f"在 mobile上启动应用{package_name}")
    
    
    class Pad(Device):
    
        def boot_app(self, package_name):
            print(f"在 pad上启动应用{package_name}")
    
    
    class DeviceFactory:
        """
        设备工厂
        """
    
        def create_device(self, device_cls_name):
            device = DeviceStack.get_device_cls(device_cls_name)
            if device:
                return device()
            else:
                raise DeviceTypeError
    
    
    class ManagerFactory:
        """
        管理工厂
        抽象工厂模式的核心,还回一个具体的工厂
    
        """
    
        def __init__(self):
            self.factory_map = {
                'connection': ConnectionFactory,
                'device': DeviceFactory,
            }
    
        def get_factory(self, factory_name):
            factory = self.factory_map.get(factory_name)
            if factory:
                return factory()
            else:
                raise FactoryTypeError(f"工厂类型错误:{factory_name} not in {self.factory_map.keys()}")
    
    
    if __name__ == "__main__":
        # 工厂方法
        con_factory = ConnectionFactory()
        usb = con_factory.create_connection("USBConnection")
        usb.connect("aaaaaa")
        dev_factory = DeviceFactory()
        mobile = dev_factory.create_device("Mobile")
        mobile.boot_app("123.apk")
        # 调用抽象工厂
        factory = ManagerFactory()
        dev_factory = factory.get_factory('device')
        # 获取 pad 设备
        pad = dev_factory.create_device("Pad")
        pad.boot_app("1111.apk")
    

    运行后的控制台输出

    image.png

    相关文章

      网友评论

          本文标题:python 抽象工厂实践+ 元类自动注册工厂类

          本文链接:https://www.haomeiwen.com/subject/nqgcaltx.html