组合模式和适配器模式的区别

组合模式(Composite Pattern)和适配器模式(Adapter Pattern)都是结构型设计模式,它们解决的问题不同,应用场景也不一样。下面我来对比一下这两种模式的区别:

1. 目标和用途

组合模式(Composite Pattern)

  • 目标:处理树形结构的对象,将"部分"与"整体"进行统一处理。
  • 用途:组合模式的主要目的是让你能够将单个对象和对象集合(例如树结构)统一处理。它解决的是部分-整体的关系,使得客户端可以像操作单个对象一样操作一组对象。

适配器模式(Adapter Pattern)

  • 目标:将一个类的接口转换为客户端所期望的接口,适配不同的接口。
  • 用途:适配器模式的目的是解决接口不兼容的问题,让不同的接口可以协同工作。它提供了一个适配层,使得原本不兼容的类可以互相调用。

2. 结构

组合模式

组合模式的核心思想是通过递归地将对象组成树形结构,部分和整体有相同的接口。无论是一个单独的对象(叶子节点)还是一个包含多个子对象的组合(树枝节点),都实现相同的接口。这样,客户端就可以统一对待单一对象和复合对象。

示例结构:

  • Component(组件接口):定义统一的操作。
  • Leaf(叶子节点):实现单一对象。
  • Composite(树枝节点):包含多个子组件,可以包含Leaf或者其他Composite对象。

适配器模式

适配器模式通过引入一个适配器类来实现接口转换。它将原本不兼容的接口转换成客户端期望的接口。

示例结构:

  • Target(目标接口):客户端期望的接口。
  • Adapter(适配器类):将源接口转化为目标接口。
  • Adaptee(源类):需要被适配的类。

3. 使用场景

组合模式

适用于需要表示树形结构的情况,比如:

  • 组织架构(员工、经理、部门等)。
  • 文件系统(文件夹和文件)。
  • UI组件(按钮、窗口、面板等)。

例如:在公司管理系统中,经理可以管理下属,员工和经理都实现统一的Employee接口。无论是一个普通员工还是一个管理着其他员工的经理,都可以通过相同的方法来处理。

适配器模式

适用于接口不兼容的情况,尤其是需要使两个本来不兼容的类能够合作时。

  • 例如:将一个旧系统的接口适配到新的系统接口中。
  • 将第三方库的接口适配到你自己的项目中。

比如你有一个第三方库提供的类,它的方法名称或参数不同于你自己系统的要求,这时你可以通过适配器模式来转换它们的接口,使它们能够顺利协作。

4. 实现区别

组合模式实现

组合模式强调统一的接口,并通过递归构建树形结构。它允许客户端通过统一接口操作复杂的层次结构,无论是叶子节点还是复合节点。客户端代码不需要关心每个节点是单一对象还是一个组合,均通过统一接口处理。

适配器模式实现

适配器模式主要是通过引入一个适配器类来转换接口。适配器类会将源类的接口转换成目标接口,以便兼容客户端的需求。

5. 总结对比

|------|----------------------------------------------|-----------------------------------------------|
| 特征 | 组合模式 | 适配器模式 |
| 目标 | 统一处理单个对象和对象的组合(树形结构)。 | 将不兼容的接口适配成客户端所期望的接口。 |
| 主要用途 | 处理部分和整体的关系(树形结构)。 | 解决不同接口不兼容的问题。 |
| 结构 | Component 接口, Leaf (叶子节点), Composite (树枝节点)。 | Target (目标接口), Adapter (适配器), Adaptee (被适配类)。 |
| 应用场景 | 组织架构、文件系统、UI组件等树形结构。 | 接口不兼容时,需转换接口以便合作。 |
| 设计目标 | 使客户端能够统一处理单个对象和组合对象。 | 使得不兼容的类可以协同工作。 |

6. 简单示例

组合模式(员工管理例子)

cpp 复制代码
class Employee {
public:
    virtual void showDetails() = 0;
};

class Developer : public Employee {
public:
    void showDetails() override {
        std::cout << "Developer details..." << std::endl;
    }
};

class Manager : public Employee {
private:
    std::vector<Employee*> subordinates;
public:
    void addSubordinate(Employee* employee) {
        subordinates.push_back(employee);
    }
    void showDetails() override {
        std::cout << "Manager details..." << std::endl;
        for (auto& subordinate : subordinates) {
            subordinate->showDetails();
        }
    }
};

适配器模式(旧接口适配到新接口)

cpp 复制代码
class Target {
public:
    virtual void request() = 0;
};

class Adaptee {
public:
    void specificRequest() {
        std::cout << "Specific request!" << std::endl;
    }
};

class Adapter : public Target {
private:
    Adaptee* adaptee;
public:
    Adapter(Adaptee* adaptee) : adaptee(adaptee) {}
    void request() override {
        adaptee->specificRequest();  // 转发请求
    }
};

总结:

  • 组合模式关注的是如何统一处理对象的部分与整体,使得单一对象和对象组合(如树形结构)具有统一的接口。
  • 适配器模式则是解决不同接口之间的不兼容问题,通过引入适配层使得接口能够互相配合工作。
相关推荐
小白不太白9503 小时前
设计模式之建造者模式
java·设计模式·建造者模式
菜菜-plus5 小时前
java 设计模式 模板方法模式
java·设计模式·模板方法模式
萨达大5 小时前
23种设计模式-模板方法(Template Method)设计模式
java·c++·设计模式·软考·模板方法模式·软件设计师·行为型设计模式
机器视觉知识推荐、就业指导7 小时前
C++设计模式:原型模式(Prototype)
c++·设计模式·原型模式
MinBadGuy8 小时前
【GeekBand】C++设计模式笔记13_Flyweight_享元模式
c++·设计模式
Clang's Blog9 小时前
23种设计模式详解(以Java为例)
java·开发语言·设计模式
程序员奇奥9 小时前
设计模式——简单工厂模型、工厂模式、抽象工厂模式、单例模式、代理模式、模板模式
单例模式·设计模式·抽象工厂模式
hxj..9 小时前
【设计模式】代理模式
java·设计模式·代理模式·动态代理
十五年专注C++开发10 小时前
C++不完整类型(Incomplete Type)的检测与避免
开发语言·c++·算法·设计模式