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

news/2024/11/27 3:20:39/

        组合模式(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. 简单示例

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

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();}}
};

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

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();  // 转发请求}
};

总结:

  • 组合模式关注的是如何统一处理对象的部分与整体,使得单一对象和对象组合(如树形结构)具有统一的接口。
  • 适配器模式则是解决不同接口之间的不兼容问题,通过引入适配层使得接口能够互相配合工作。

http://www.ppmy.cn/news/1550221.html

相关文章

力扣—53. 最大子数组和

53. 最大子数组和 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4…

sklearn中常用数据集简介

scikit-learn库中提供了包括分类、回归、聚类、降维等多种机器学习任务所需的常用数据集&#xff0c;方便进行实验和研究&#xff0c;它们主要被封装在sklearn.datasets中&#xff0c;本文对其中一些常用的数据集进行简单的介绍。 1.Iris&#xff08;鸢尾花&#xff09;数据集…

JDK1.8新增特性

新特性&#xff1a; Lambda表达式: &#xff08;语法三要素&#xff1a;参数、箭头、代码&#xff09; JDK1.8引入的一种新语法Lambda表达式,它简化了匿名内部类的使用和提高代码的可读性。 /**正常写法创建Runable**/ Runnable runnable new Runnable() {Overridepublic voi…

HarmonyOS Next 简单上手元服务开发

HarmonyOS Next 简单上手元服务开发 万物互联时代&#xff0c;人均持有设备量不断攀升&#xff0c;设备种类和使用场景更加多样&#xff0c;使得应用开发、应用入口变得更加复杂。在此背景下&#xff0c;应用提 供方和用户迫切需要一种新的服务提供方式&#xff0c;使应用开发…

MySQL基础大全(看这一篇足够!!!)

文章目录 前言一、初识MySQL1.1 数据库基础1.2 数据库技术构成1.2.1 数据库系统1.2.2 SQL语言1.2.3 数据库访问接口 1.3 什么是MySQL 二、数据库的基本操作2.1 数据库创建和删除2.2 数据库存储引擎2.2.1 MySQL存储引擎简介2.2.2 InnoDB存储引擎2.2.3 MyISAM存储引擎2.2.4 存储引…

vue3+elementui-plus el-dialog全局配置点击空白处不关闭弹窗

在与main.ts同级下的plugins文件夹&#xff08;如果没有&#xff0c;新建一个&#xff09;下建一个element.js文件&#xff08;名字随便取&#xff09; element.js文件内容如下&#xff1a; import ElementPlus from element-plus export default (app) > {console.log(app…

【Axure高保真原型】或和且条件

今天和大家分享或和且条件案例的原型模板&#xff0c;效果包括&#xff1a; 可以选择指标、等式和填写对应值构成条件等式&#xff1b; 点击添加条件按钮&#xff0c;可以增加一行新的条件&#xff1b; 点击所在行的号按钮&#xff0c;可以在该行下方添加一行新的条件&#x…

H.265流媒体播放器EasyPlayer.js网页全终端安防视频流媒体播放器可以播放本地视频吗

H.264/H.265播放器EasyPlayer.js主要用于在网页上实现视频播放功能&#xff0c;特别是针对RTSP流的播放。它允许开发者在不需要安装额外插件或软件的情况下&#xff0c;直接在网页中嵌入和播放来自监控摄像头或其他RTSP源的视频流。 可以播放本地视频吗&#xff1f; 回答&…