• Python之适配器模式


    一、介绍

    结构型设计模式:主要用来处理一个系统中不同实体之间关系,即将类或者对象组合在一起,重新组成为一种新的、功能更强大的结构。

    1. 类结构型模式:多个类组合而成的系统。
    2. 对象结构型模式:在一个类中定义另外一个类的实例,通过类与对象的组合形成更大的系统,可以通过类中的对象属性去调用这个对象的方法。

    适配器模式:也是属于设计模式中的结构型模式。
      适配器模式主要用于 帮助我们实现两个不兼容接口之间的兼容。

    二、适配器模式

    1、对象结构型适配器示例

    假设存在一套旧的系统ExecuteCmd类,用来执行一些系统命令。

    import subprocess
    
    
    class ExecuteCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def cmd_exe(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code

    客户端要执行命令的时候,只需要调用这个类的实例方法cmd_exe即可:

    old_obj = ExecuteCmd("ls -l").cmd_exe()

    现在有一个新的系统,仍然是用来执行一些系统命令,但是新的调用方式改变了。

    class NewCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def run_cmd(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code

    新的调用方式是:

    new_obj = NewCmd("ls -l").run_cmd()

    假设由于新系统支持的命令更多,我们想要把新系统也提供给客户端使用,但是客户端只知道使用某个实例的cmd_exe方法,并不知道新系统的调用方式改变了。

    在不改变新系统NewCmd类的前提下,我们该如何做才能让客户端仍然能正常调用呢?
    此时就需要用到适配器!我们可以创建一个通用的Adapter类,将一些不同接口的对象适配到一个统一接口中。

    在初始化方法init()中,用一个属性obj把我们想要适配的对象保存下来, adapted_methods是一个字典,用于转换接口,key是客户端要调用的方法,value是想要适配的对象真正被调用的方法。

    适配器类定义如下:

    class Adapter:
        def __init__(self, obj, adapted_methods):
            self.obj = obj
            self.__dict__.update(adapted_methods)
    
        def __getattr__(self, item):
            return self.obj.item

    使用方法如下

    # 旧接口可以不适配
    old_obj = ExecuteCmd("ls -l").cmd_exe()
    
    # 新接口需要进行适配
    new_obj = NewCmd("ls -l")
    trans_obj = Adapter(new_obj, dict(cmd_exe=new_obj.run_cmd))
    # 适配完成后,就可以跟旧系统一样使用cmd_exe执行命令
    trans_obj.cmd_exe()

    完整的代码展示

    import subprocess
    
    
    class ExecuteCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def cmd_exe(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code
    
    
    class NewCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def run_cmd(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code
    
    
    class Adapter:
        def __init__(self, obj, adapted_methods):
            self.obj = obj
            self.__dict__.update(adapted_methods)
    
        def __getattr__(self, item):
            return self.obj.item
    
    
    # 旧接口可以不适配
    old_obj = ExecuteCmd("calc").cmd_exe()
    
    # 新接口需要进行适配
    new_obj = NewCmd("calc")
    # 这里将新系统的run_cmd方法适配成旧系统的cmd_exe方法
    trans_obj = Adapter(new_obj, dict(cmd_exe=new_obj.run_cmd))
    # 适配完成后,就可以跟旧系统一样使用cmd_exe执行命令
    trans_obj.cmd_exe()

    2、类结构型适配器示例

    如果我们希望直接使用一个新的类去适配旧系统的接口时,也可以使用类结构型适配器,方法如下:

    1. 创建一个新的类
    2. 继承需要进行转换的类
    3. 在新的类中实现旧系统的接口
    import subprocess
    
    
    class ExecuteCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def cmd_exe(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code
    
    
    class NewCmd:
        def __init__(self, cmd):
            self.cmd = cmd
    
        def run_cmd(self):
            result = ""
            result_code = 0
            try:
                result = subprocess.check_output(self.cmd, shell=True)
            except subprocess.CalledProcessError as e:
                result_code = 1
            return result, result_code
    
    
    class Adapter(NewCmd):
        """继承新系统的类"""
    
        def cmd_exe(self):
            """直接在适配器中实现旧系统的接口"""
            return self.run_cmd()
    
    
    # 旧接口
    old_obj = ExecuteCmd("calc").cmd_exe()
    
    # 新接口需要进行适配
    new_obj = Adapter("calc").cmd_exe()
  • 相关阅读:
    iOS开发之字符串去掉首尾空格换行
    iOS开发之截取UIScrollView长图方法、截长图
    iOS开发之语音录制
    iOS开发之程序各种状态监听
    iOS开发之监听应用进入前台后台
    iOS开发之波浪动画效果
    mysql 主从一致性检查
    git 备份和恢复
    tomcat server.xml配置文件 解析
    检查MySQL主从数据一致性
  • 原文地址:https://www.cnblogs.com/Zzbj/p/15778989.html
Copyright © 2020-2023  润新知