一个简单的适配器模式例子

Java的老一辈开发者应该比较熟悉Vector,Stack,Hashtable等集合类。它们的elements()返回一个实现了Enumeration接口的实现类。

但是自从出现Iterator以后,就很少再使用Enumeration了。

Iterator接口声明了三个方法: hasNext(),next(),remove()方法。

而Enumeration只声明了hasMoreElements()和nextElement()方法。分别对应于Iterator的hasNext和next方法。


假设现在客户端的代码只接受接口为Iterator的实现集合。但是现在我们已经拥有了Enumeration集合类。所以这个时候,我们可以使用适配器模式来解决接口不兼容的问题。

/*
 * 一个简单的适配器模式例子
 * 
 * 具体角色:
 * Target  - Iterator
 * Adaptor - EnumerationIterator
 * Adaptee - Enumeration
 * client  - print method 
 */
package pattern.adapter;

import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

/**
 * 把Enumeration接口转换成Iterator接口的适配器 
 * 适配器模式中的角色 - adaptor
 */
class EnumerationIterator<E> implements Iterator<E> {
	
	/**
	 * 被适配的接口
	 * 适配器模式中的角色 - adaptee 
	 */
	private Enumeration<E> enums;

	public EnumerationIterator(Enumeration<E> enums) {
		this.enums = enums;
	}
	
	@Override
	public boolean hasNext() {
		return enums.hasMoreElements();
	}

	@Override
	public E next() {
		return enums.nextElement();
	}

	/**
	 * 因为Enumeration接口不支持remove操作,所以这里简单地抛出异常
	 */
	@Override
	public void remove() {
		throw new UnsupportedOperationException();
	}

}
public class Main {

	public static void main(String[] args) {
		
		Vector<String> students = new Vector<String>(Arrays.asList("Benson","Steven Jobs","Bill Gates","James Gosling","Doug Lea"));
		Enumeration<String> enums = students.elements();  // 接口为Enumeration,与客户端的Iterator不兼容。
Iterator
		print(new EnumerationIterator<String>(enums)); // EnumerationIterator为适配器,将不兼容的Enumeration转换成客户端需要的Iterator接口
	}
	
	/**
	 * 客户端只接受Iterator接口的实现类
	 * 适配器模式中的角色 - Client
	 */
	static void print(Iterator<String> iterator) {
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
}


<think> 我们来实现一个适配器模式例子适配器模式通常用于将一个类的接口转换成客户希望的另外一个接口。以下是一个经典示例:我们有一个目标接口(Target),需要适配一个已有但接口不兼容的类(Adaptee),通过适配器(Adapter)来使Adaptee的接口符合Target的需求。 ### 场景设定: - **Target(目标接口)**:定义客户端期望的接口,这里假设是一个`Request`方法。 - **Adaptee(被适配者)**:已经存在的类,但其接口与Target不兼容,它有一个`SpecificRequest`方法。 - **Adapter(适配器)**:通过继承或组合Adaptee,将Adaptee的接口转换成Target的接口。 ### 代码实现: ```cpp #include <iostream> #include <string> // 目标接口:客户端期望的接口 class Target { public: virtual ~Target() = default; virtual void Request() const { std::cout << "Target: 默认目标行为。" << std::endl; } }; // 被适配者:已有类,但接口不兼容 class Adaptee { public: void SpecificRequest() const { std::cout << "Adaptee: 被适配者的特定行为。" << std::endl; } }; // 适配器:通过组合方式实现(对象适配器) class Adapter : public Target { private: Adaptee *adaptee_; // 持有被适配者对象的指针(也可以是引用或值成员) public: Adapter(Adaptee *adaptee) : adaptee_(adaptee) {} void Request() const override { // 转换调用:将Request调用转发给Adaptee的SpecificRequest if (adaptee_) { adaptee_->SpecificRequest(); } } }; // 客户端代码 int main() { // 创建被适配者对象 Adaptee *adaptee = new Adaptee(); // 创建适配器,将被适配者传入 Target *target = new Adapter(adaptee); // 客户端通过目标接口调用 target->Request(); // 输出: Adaptee: 被适配者的特定行为。 // 清理 delete target; delete adaptee; return 0; } ``` ### 另一种实现:类适配器(通过多继承) ```cpp // 类适配器:通过继承Adaptee和Target(如果语言支持多继承) class ClassAdapter : public Target, public Adaptee { public: void Request() const override { // 直接调用父类Adaptee的方法 SpecificRequest(); } }; // 使用类适配器的客户端代码 int main() { Target *target = new ClassAdapter(); target->Request(); // 输出: Adaptee: 被适配者的特定行为. delete target; return 0; } ``` ### 模式说明: 1. **组合方式(对象适配器)**: - 适配器持有被适配者的实例(指针或引用) - 灵活性高,可以适配多个不同的被适配者 2. **继承方式(类适配器)**: - 适配器同时继承目标接口和被适配者 - 需要编程语言支持多继承(C++支持) - 更直接,但灵活性较低 ### 适用场景: - 已有类无法修改,但其功能需要被复用 - 希望创建一个可复用的类,与多个不相关的类协作 - 需要统一多个不同子类的接口 §§相关问题§§ 1. 在适配器模式中,对象适配器和类适配器的主要区别是什么? 2. 如何避免适配器模式中可能出现的循环依赖问题? 3. 适配器模式与代理模式在实现上有何异同? 4. 在C++中,使用智能指针管理适配器和被适配者对象时需要注意什么? 5. 如何实现一个双向适配器(同时适配两个不同的接口)? </think> 以下是一个使用C++实现的**适配器模式(Adapter Pattern)** 的完整示例。适配器模式用于将一个类的接口转换成客户端期望的另一个接口,常用于解决接口不兼容问题。 ### 场景描述 假设我们有一个第三方提供的**XML解析器类**(`XMLParser`),它只能处理XML格式数据。但我们的系统需要使用**JSON格式**数据。我们通过适配器模式,创建一个适配器类将XML解析器"伪装"成JSON解析器。 ```cpp #include <iostream> #include <string> // ================= 1. 目标接口(期望的JSON解析接口) ================= class JSONParser { public: virtual ~JSONParser() = default; virtual void parseJSON(const std::string& jsonData) = 0; }; // ================= 2. 被适配者(现有的XML解析器) ================= class XMLParser { public: void parseXML(const std::string& xmlData) { std::cout << "解析XML数据: " << xmlData << std::endl; } }; // ================= 3. 适配器(将XMLParser适配为JSONParser) ================= class XMLToJSONAdapter : public JSONParser { private: XMLParser* xmlParser; // 持有被适配对象的指针 public: explicit XMLToJSONAdapter(XMLParser* parser) : xmlParser(parser) {} // 关键:实现JSON接口,内部调用XML功能 void parseJSON(const std::string& jsonData) override { // 将JSON数据转换为XML格式(简单模拟) std::string xmlData = "XML格式数据: " + jsonData; // 调用被适配者的方法 xmlParser->parseXML(xmlData); } }; // ================= 客户端代码 ================= int main() { // 创建被适配者(现有XML解析器) XMLParser xmlParser; // 创建适配器,注入被适配对象 XMLToJSONAdapter adapter(&xmlParser); // 客户端使用JSON接口(实际由XML解析器处理) std::cout << "客户端调用JSON解析接口:" << std::endl; adapter.parseJSON("{\"name\":\"John\", \"age\":30}"); return 0; } ``` ### 输出结果 ``` 客户端调用JSON解析接口: 解析XML数据: XML格式数据: {"name":"John", "age":30} ``` ### 模式解析 1. **目标接口(Target)**:`JSONParser` - 定义客户端期望的接口(`parseJSON`方法) 2. **被适配者(Adaptee)**:`XMLParser` - 已存在的类,但接口不兼容 3. **适配器(Adapter)**:`XMLToJSONAdapter` - 继承目标接口(`JSONParser`) - 持有被适配者的实例(组合关系) - 在目标接口方法中调用被适配者的功能 ### 适配器类型选择 - **对象适配器**(本例实现):使用组合关系,更灵活(可适配多个不同的被适配者) - **类适配器**:通过多重继承实现(需继承目标和被适配者),C++支持但需注意菱形继承问题 ### 适用场景 1. 集成第三方库时接口不兼容 2. 重用遗留代码,但需符合新接口规范 3. 创建统一接口处理多个类似组件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值