首页 > 编程语言 >Python实现软件设计模式7:适配器模式 Adapter Pattern

Python实现软件设计模式7:适配器模式 Adapter Pattern

时间:2024-01-11 12:35:22浏览次数:26  
标签:Adapter __ Python 适配 适配器 模式 self def

动机

有两个不存在直接继承或关联关系的类A、B, A希望能利用到B类中某个已存在的、功能完善的方法,而不再去具体实现A的接口源码;适配器模式使接口不兼容的那些类可以一起工作。

主要角色

  • 目标类 Target 抽象接口类
  • 适配者 Adaptee
  • 适配器 Adapter 具体实现接口
  • 客户端 Client

客户端针对目标类编程,希望调用目标类的某个方法;而适配者中已经提供了关于Target中该方法的完整实现。

分类

具体分为两种类型,类适配器、对象适配器(使用频率更高、更灵活)

  • 类适配器: Target与Adapter是继承关系,Adapter与Adaptee也是继承关系。由于语法的限制,有些语言中一个类只能单继承一个父类,所以类适配器可能不太适合使用;并且即使能多继承、假设适配多个父类这样也不太好扩展。
public class Adapter extends Adaptee implements Target{
    public void request(){
        super.specificRequest();
    }
}

  • 对象适配器: Target与Adapter是继承关系,然而Adapter与Adaptee之间是委派关系(在Adapter中定义一个Adaptee的对象)。对象适配器的Java版本伪代码如下:
public class Adapter extends Target{
    private Adaptee adaptee;    // 委派一个对象

    public Adapter(Adaptee x){
        this.adaptee = x;
    }
    
    public void request(){
        adaptee.specificRequest(); 
    }
}

案例:仿生机器人

需要设计一个可以模拟各种动物行为的机器人,在机器人中定义一系列方法,如叫喊cry、移动move;如果已存在一个狗的类,其中已经定义了功能类似的wang和run方法;

Python版本代码


from abc import ABC,abstractmethod

class Robot(ABC):
    @abstractmethod
    def cry(self):
        pass
    
    @abstractmethod
    def move(self):
        pass

class Dog:
    def wang(self):
        print("狗儿_wang wang wang!")
    
    def run(self):
        print("狗儿_run run run!")

class Bird:
    def tweedle(self):
        print("鸟儿_ji ji ji!")
    
    def fly(self):
        print("鸟儿_fly fly fly!")

# 对象适配1
class DogAdapter(Robot):    # 让机器人适配狗特性的适配器类
    def __init__(self):
        self.__adaptee = Dog()
    
    def cry(self):
        print("机器人模仿狗的叫喊:")
        self.__adaptee.wang()
    
    def move(self):
        print("机器人模仿狗的移动:")
        self.__adaptee.run()

# 对象适配2
class BirdAdapter(Robot):    # 让机器人适配狗特性的适配器类
    def __init__(self):
        self.__adaptee = Bird()
    
    def cry(self):
        print("机器人模仿鸟的叫喊:")
        self.__adaptee.tweedle()
    
    def move(self):
        print("机器人模仿鸟的移动:")
        self.__adaptee.fly()

class Client:
    def __init__(self, AdapterName):
        self.Adapter = AdapterName
    
    def run(self):
        try:
            robot = eval(self.Adapter)()
            robot.cry()
            robot.move()

        except NameError:
            print(f"Error! Robot adapter '{self.Adapter}' doesn't exits...")

if __name__ == '__main__':
    rb1 = Client('DogAdapter')
    rb1.run()
    print()
    rb2 = Client('BirdAdapter')
    rb2.run()

总结

优点

  • 将目标类与适配者类解耦,通过引入一个适配器来重用现有的适配者类,无需修改原有的结构
  • 增加了类的透明性和复用性,提高了适配者的复用性,同一个适配者类可以再多个不同的系统中复用
  • 灵活性和扩展性好
  • 类适配器模式:置换一些适配者的方法很方便
  • 对象适配器模式:可以把多个不同的适配者适配(委派)到同一个目标

缺点

  • 类适配器模式:一次最多智能适配一个适配者类,不可以适配多个适配者;Java语义下的目标抽象类只能声明为接口,不能为类;Java语义下的适配者类不能为final类(因为final类不能有子类)

  • 对象适配器模式:适配器中置换适配者类的某些方法比较麻烦

标签:Adapter,__,Python,适配,适配器,模式,self,def
From: https://www.cnblogs.com/Higgerw/p/17958301

相关文章

  • python第三节:Str字符串类型(3)
    str.index(sub[, start[, end]])类似于 find(),但在找不到子字符串时会引发 ValueError。例子:str1='mynameisjack!'print(str1.index('i'))print(str1.index('b'))结果:Traceback(mostrecentcalllast): File"D:/pythonProject/test/test2024011......
  • IntelliJ IDEA Debug模式下结束后继续执行代码问题
    1.默认的配置默认的Debug模式下点击Stop后会继续执行代码。2.设置不继续执行后续代码Preferences->Build,Execution,Deployment->Debugger找到Java那一栏下边可以看到Killthedebugprocessimmediately选项,勾选后点击确定就可以了。或是直接在设置搜索框里输入Kil......
  • 您好!您可以使用Python中的Pandas库来转换数据框为思维导图和流程图。以下是一些代码片
    您好!您可以使用Python中的Pandas库来转换数据框为思维导图和流程图。以下是一些代码片段,可帮助您开始:-要将数据框转换为思维导图,请使用`graphviz`库。您可以使用以下代码片段:```pythonfromgraphvizimportDigraphimportpandasaspddf=pd.DataFrame({'A':[1,2,3],'B......
  • conda、python、pip离线管理环境安装依赖包
    第一步:当你使用conda创建一个全新的环境,而你现在处于断网工作状态,condacreate-nexample--offline 这一步表示断网状态下创建conda环境,但是只有初始环境,没有python依赖包,这时,condacreate-nexample--clonebase这一步将base环境中的基础依赖包复制到你当前的离线环境中......
  • python 处理pdf加密文件
    近期有同事需要提取加密的pdf文件,截取其中的信息,并且重构pdf文件。网上没有搜到相关的pdf操作,于是咨询了chatgpt,给出了pypdf2的使用案例。但是时间比较久远了,很多库内的调用接口都已经更新了。于是自行到官方的库内学习相关接口使用。整理的处理代码如下:#-*-coding:utf-8-*......
  • 掌握Java Future模式及其灵活应用
    第1章:引言大家好,我是小黑,今天咱们来聊聊Future。咱们程序员在日常工作中,肯定都遇到过需要处理耗时任务的情况,特别是在Java领域。比如说,小黑要从网络上下载数据,或者要执行一个计算密集型任务,这些操作都可能需要花费一些时间。在这种场景下,如果小黑还要保持程序的响应性,就得用到异......
  • python第三节:Str字符串类型(2)
    str.format(*args, **kwargs)执行字符串格式化操作。语法:点号前面是一个带槽(由大括号表示)的字符串,字符串里面可以设置各种参数和格式控制标记,后面是format和替换的字符串。{参数序号:格式控制标记}如下六个按照顺序使用。:填空对齐宽度逗号精度类型冒号用于填充的单个字符<左对齐>......
  • # yyds干货盘点 # 盘点一个Python自动化办公的需求——一键批量插图到Excel指定单元格
    大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Python自动化办公的问题,问题如下:大佬们,昨天我在做插入excel图片的时候想起一个需求,好像挺难办的,也蛮现实的。比如每个图片是有名称的,但在做excel的时候,能不能按照excel中的名称调用图片插入。就像下面这样......
  • 【设计模式】模板方法模式——模板方法模式在JDK源码中的应用
    模板方法模式在JDK源码里最典型的实现就是AQSAbstractQueuedSynchronizerAQS(AbstractQueuedSynchronizer)的部分代码如下:publicabstractclassAbstractQueuedSynchronizerextendsAbstractOwnableSynchronizerimplementsjava.io.Serializable{//……代码......
  • 一个 python 拆解文本文件的工具
    背景你是否有遇到过文本文档太大无法打开的情况?比如说压测了好几天,生成了一个十几G的日志文件。下面这个脚本可以帮助你将一个大文件分解成一个小文件。假设文件名位:splitfile.py使用方法位:pythonsplitfile.pylog20该文件将会将log文件拆分成log.0log.1log.2...l......