《设计模式的艺术》笔记 - 适配器模式

介绍

适配器模式将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器。

实现

对象适配器模式

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class Target {  // 目标类
public:
    virtual void request() = 0;
};

class Adaptee {     // 适配者类
public:
    void specificRequest();
};

class Adapter : public Target { // 适配器类
public:
    Adapter(Adaptee *adaptee);
    void request() override;

private:
    Adaptee *m_adaptee;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

Adapter::Adapter(Adaptee *adaptee) {
    m_adaptee = adaptee;
}

void Adapter::request() {
    if (m_adaptee) {
        m_adaptee->specificRequest();
    }
}

void Adaptee::specificRequest() {
    std::cout << "Adaptee被适配" << std::endl;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Adaptee *adaptee = new Adaptee;
    Target *target = new Adapter(adaptee);
    target->request();
    delete target;
    delete adaptee;

    return 0;
}

类适配器模式

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class Target {  // 目标类
public:
    virtual void request() = 0;
};

class Adaptee {     // 适配者类
public:
    void specificRequest();
};

class Adapter : public Target, public Adaptee { // 适配器类
public:
    void request() override;

};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"


void Adapter::request() {
    specificRequest();
}

void Adaptee::specificRequest() {
    std::cout << "Adaptee被适配" << std::endl;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Target *target = new Adapter();
    target->request();
    delete target;

    return 0;
}

双向适配器

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class Target {  // 目标类
public:
    void request();
};

class Adaptee {     // 适配者类
public:
    void specificRequest();
};

class Adapter { // 适配器类
public:
    Adapter(Target *target);
    Adapter(Adaptee *adaptee);
    void request();
    void specificRequest();

private:
    Target *m_target;
    Adaptee *m_adaptee;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

void Target::request() {
    std::cout << "Target被适配" << std::endl;
}

Adapter::Adapter(Target *target) {
    m_target = target;
}

Adapter::Adapter(Adaptee *adaptee) {
    m_adaptee = adaptee;
}

void Adapter::request() {
    if (m_adaptee) {
        m_adaptee->specificRequest();
    }
}

void Adapter::specificRequest() {
    if (m_target) {
        m_target->request();
    }
}

void Adaptee::specificRequest() {
    std::cout << "Adaptee被适配" << std::endl;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Target *target = new Target();
    Adaptee *adaptee = new Adaptee();
    Adapter *adapter = new Adapter(target);
    adapter->specificRequest();
    delete adapter;
    adapter = new Adapter(adaptee);
    adapter->request();
    delete adapter;
    delete adaptee;
    delete target;

    return 0;
}

缺省适配器模式

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class ServiceInterface {    // 适配者接口
public:
    virtual void request() = 0;
    virtual void request2() = 0;
    virtual void request3() = 0;
};

class AbstractService : public ServiceInterface {     // 缺省适配器类
public:
    virtual void request() override;

    virtual void request2() override;

    virtual void request3() override;
};

class Adaptee {     // 适配者类
public:
    void specificRequest();
};

class Adapter : public AbstractService { // 具体适配器类
public:
    Adapter(Adaptee *adaptee);
    void request() override;

private:
    Adaptee *m_adaptee;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

Adapter::Adapter(Adaptee *adaptee) {
    m_adaptee = adaptee;
}

void Adapter::request() {
    if (m_adaptee) {
        m_adaptee->specificRequest();
    }
}

void Adaptee::specificRequest() {
    std::cout << "Adaptee被适配" << std::endl;
}

void AbstractService::request() {
    std::cout << "缺省函数request" << std::endl;
}

void AbstractService::request2() {
    std::cout << "缺省函数request2" << std::endl;
}

void AbstractService::request3() {
    std::cout << "缺省函数request3" << std::endl;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Adaptee *adaptee = new Adaptee();
    Adapter *adapter = new Adapter(adaptee);
    adapter->request();
    adapter->request2();
    adapter->request3();
    delete adapter;
    delete adaptee;

    return 0;
}

总结

优点

  1. 将目标类和适配者类解耦。通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。

  2. 增加了类的透明性和复用性。将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者类的复用性,同一个适配者类可以在多个不同的系统中复用。

  3. 灵活性和扩展性都非常好。通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合开闭原则。

缺点

  1. 对于Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。

  2. 适配者类不能为最终类,例如在Java中不能为final类,C#中不能为sealed类。

  3. 在Java、C#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。

适用场景

  1. 系统需要使用一些现有的类,而这些类的接口(例如方法名)不符合系统的需要,甚至没有这些类的源代码。

  2. 想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。

练习

对象适配器模式

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class Encryption {  // 目标类
public:
    virtual std::string encrypt(std::string data) = 0;
};

class ThirdLib {     // 适配者类
public:
    std::string specificEncrypt(std::string data);
    std::string specificDecrypt(std::string data);
};

class AdapterEncyption : public Encryption {    // 适配器类
public:
    AdapterEncyption(ThirdLib *thirdLib);
    ~AdapterEncyption();
    std::string encrypt(std::string data) override;

private:
    ThirdLib *m_thirdLib;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

AdapterEncyption::AdapterEncyption(ThirdLib *thirdLib) {
    m_thirdLib = thirdLib;
}

AdapterEncyption::~AdapterEncyption() {
    if (m_thirdLib) {
        delete m_thirdLib;
    }
}

std::string AdapterEncyption::encrypt(std::string data) {
    if (m_thirdLib) {
        return m_thirdLib->specificEncrypt(data);
    }
    return data;
}

std::string ThirdLib::specificEncrypt(std::string data) {
    return "加密后的" + data;
}

std::string ThirdLib::specificDecrypt(std::string data) {
    return "解密后的" + data;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    ThirdLib *thirdLib = new ThirdLib();
    Encryption *encryption = new AdapterEncyption(thirdLib);
    std::string data = encryption->encrypt("口令");
    std::cout << data << std::endl;
    data = encryption->encrypt("邮箱");
    std::cout << data << std::endl;

    return 0;
}

类适配器模式

myclass.h

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H

#include <iostream>

class Encryption {  // 目标类
public:
    virtual std::string encrypt(std::string data) = 0;
};

class ThirdLib {     // 适配者类
public:
    std::string specificEncrypt(std::string data);
    std::string specificDecrypt(std::string data);
};

class AdapterEncyption : public Encryption, public ThirdLib {    // 适配器类
public:
    AdapterEncyption();
    ~AdapterEncyption();
    std::string encrypt(std::string data) override;
};

#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

cpp 复制代码
//
// Created by yuwp on 2024/1/12.
//

#include "myclass.h"

AdapterEncyption::AdapterEncyption() {

}

AdapterEncyption::~AdapterEncyption() {

}

std::string AdapterEncyption::encrypt(std::string data) {
    return specificEncrypt(data);
}

std::string ThirdLib::specificEncrypt(std::string data) {
    return "加密后的" + data;
}

std::string ThirdLib::specificDecrypt(std::string data) {
    return "解密后的" + data;
}

main.cpp

cpp 复制代码
#include <iostream>
#include <mutex>
#include "myclass.h"

int main() {
    Encryption *encryption = new AdapterEncyption();
    std::string data = encryption->encrypt("口令");
    std::cout << data << std::endl;
    data = encryption->encrypt("邮箱");
    std::cout << data << std::endl;
    delete encryption;

    return 0;
}
相关推荐
ly76891 分钟前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
demodeom37 分钟前
Win11 + RTX 5080 本地 Coding 模型测试笔记(已弃坑)
笔记
peijiping1 小时前
Agent 工具执行:并行(parallel_tool_calls)和后台(run_in_background)到底有什么区别? (学习笔记)
笔记·学习·ai agent·claude code
Oll Correct1 小时前
Adobe illustrator 案例四:吃豆人 (Pac-Man)图标绘制
笔记·ui·adobe·illustrator
LuminousCPP2 小时前
单链表专题(四)-刷题复盘篇-LeetCode 138 随机链表复制|原地拷贝法突破复杂指针操作
数据结构·笔记·算法·leetcode·链表
萌新小白YXY2 小时前
SAE J1587/SAE J1708 协议笔记
笔记·单片机·嵌入式硬件
IT古董2 小时前
【MES学习笔记系列】MES 推荐书籍与资源
笔记·学习
一米阳光86612 小时前
软考(中级)软件设计师核心笔记(9)算法——时间复杂度与空间复杂度、查找算法、排序算法
笔记·算法·职场发展·软考·软件设计师·中级职称
米饭不加菜2 小时前
常用基本求导公式与法则(超详细推导版——上)
经验分享·笔记
AI人工智能+电脑小能手3 小时前
大白话说Java设计模式-14-适配器模式(业务实战篇)
java·设计模式·适配器模式·系统兼容·多渠道对接