适配器模式 adapter 结构型 设计模式(九)
现实世界中的适配器模型
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082734102-1437497622.png)
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082742749-1893411159.png)
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082749910-671332012.png)
现实世界中适配器模式 角色分类
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082753380-1699013896.png)
现实世界到代码的转换 电源插座代码示例
港版插座面板
package adapter;
/**目标角色 Target 接口
* 香港地区使用的插座面板,提供输出电流的功能
* @author noteless
*
*/
public interface TargetHongkongPanelInterface {
public void offerHongKongElectricity();
} package adapter;
/**目标角色 Target 某个具体的港版插座面板 实现类
* 香港地区使用的插座面板,提供输出电流的功能
* @author noteless
*
*/
public class TargetHongkongPanel implements TargetHongkongPanelInterface{
@Override
public void offerHongKongElectricity() {
System.out.println("港版面板 提供电流");
}
}
大陆地区插座面板
package adapter;
/**被适配角色 Adaptee 接口
* 大陆地区使用的插座面板,提供输出电流的功能
* @author noteless
*
*/
public interface AdapteeChinaMainlandPanelInterface {
public void offerChinaMainlandElectricity();
} package adapter;
/**被适配角色 Adaptee 某种具体类型的插座面板 实现类
* 大陆地区使用的插座面板,提供输出电流的功能
* @author noteless
*/ public class AdapteeChinaMainlandPanel implements AdapteeChinaMainlandPanelInterface{
@Override
public void offerChinaMainlandElectricity() {
System.out.println("国标面板 提供电流"); }
}
港版插头
package adapter;
/**客户角色 Client 港版插头
* @author noteless
*
*/
public class ClientHongKongSocket {
/**接受港版插座面板作为参数
* 港版插头,插入到港版插座面板
* @param targetHongkongPanel
*/
public void plugIn(TargetHongkongPanelInterface targetHongkongPanel) {
targetHongkongPanel.offerHongKongElectricity();
}
/*
* 测试主程序,港版插头 插入到适配器上
* 适配器插入到大陆面板上
*/
public static void main(String ...args) {
//港版插头
ClientHongKongSocket socket = new ClientHongKongSocket();
//大陆面板
AdapteeChinaMainlandPanel adapteeChinaMainlandPanel = new AdapteeChinaMainlandPanel();
//适配器
Adapter adapter = new Adapter(adapteeChinaMainlandPanel);
//港版插头 插到 适配器上
socket.plugIn(adapter);
}
}
插头适配器
package adapter;
/**适配器角色 Adapter
* 实现目标角色 TargetHongkongPanelInterface
* 组合使用被适配角色 AdapteeChinaMainlandPanelInterface
* 将对目标角色的方法调用转换为被适配角色的方法调用
* @author noteless
*
*/
public class Adapter implements TargetHongkongPanelInterface{
private AdapteeChinaMainlandPanelInterface adapteeChinaMainlandPanel; Adapter(AdapteeChinaMainlandPanel adapteeChinaMainlandPanel){
this.adapteeChinaMainlandPanel = adapteeChinaMainlandPanel;
} @Override
public void offerHongKongElectricity() {
adapteeChinaMainlandPanel.offerChinaMainlandElectricity();
}
}
执行港版插头的测试main方法
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082755678-85262300.png)
UML图
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082756074-1195769481.png)
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082756466-1082541156.png)
OOP中的适配器模式详解
意图:
将一个类的接口转换成客户希望的另外一个接口。
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.
注意:此处说的接口,并不是单纯的指Interface,而是指一切可以提供方法调用的类型,可能是接口也可能是类
|
客户使用适配器的过程:
客户通过目标接口调用适配器的方法,对适配器发出请求
适配器使用被适配者接口把请求进行处理
客户接收到调用的结果,但是并未察觉这一切是适配器在起转换作用.
|
适配器分类
适配器三种模式 |
类适配器 对象适配器 接口适配器 |
想要把一个类的接口转换为客户希望的另外一个接口 必须要有输入输出,有目标 有源 所以作为一个适配器,必须要 一手拿着被适配者也就是源 另一手拿着的是目标 想要转变为目标,那么必须得同目标时一样的类型, 在oop中想要成为目标类型 要么继承 要么实现 想要拥有被适配者,要么继承,要么实现,要么就是关联(拥有一个对象) 三种方式可以理解为按照 拥有被适配者 的方式进行划分的 如果继承Adaptee,那么就是类 适配器 如果拥有一个Adaptee,也就是拥有一个Adaptee对象,那么就是对象 适配器 如果实现Adaptee,那么就是 接口适配器 |
类适配器
根据上面的描述,如果继承Adaptee,那么就是类 适配器,
在Java中不允许多继承,既然已经继承了Adaptee ,那么就必须要求目标是一个接口(此处接口就是Interface)
这就有一定的局限性
而且,既然是继承被适配者类,那么,被适配者的子类拥有的方法和行为,他并不能拥有,也就是说不能适配被适配者的子类
|
优点,那就是,适配器作为被适配者的子类,自然拥有更多的操作空间,比如重写方法 |
对象适配器 |
如同我们上面的例子一样,如果把被适配者当做一个属性对象放到适配器中,这就是对象适配器
显然,他不要求目标一定是接口, 继承还是实现都可以
同类适配器比较的话,显然,他不能对被适配者 原来的一些方法进行操作,只能进行使用,不过也无伤大雅,不算缺点
因为他是拥有一个被适配者类型的对象,那么,被适配者和他的子类显然都可以作为具体的对象传入
|
接口适配器 按照我们的描述,如果实现了被适配者 Adaptee 那么就是接口适配器 具体说来: 当不需要全部实现接口提供的方法时 可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法) 那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求 它适用于一个接口不想使用其所有的方法的情况 |
接口适配器示例
接口
package interfaceadapter;
public interface Interfaces {
public void method1();
public void method2();
public void method3();
public void method4();
public void method5();
}
抽象类
package interfaceadapter;
/**
* @author noteless
*
*/
public abstract class AbstractClass implements Interfaces {
@Override
public void method1() { }
@Override
public void method2() { }
@Override
public void method3() { }
@Override
public void method4() { }
@Override
public void method5() { }
}
两个实现类
package interfaceadapter;
public class ImplementClass1 extends AbstractClass {
@Override
public void method1() {
System.out.println("method1 called ");
}
@Override
public void method3() {
System.out.println("method3 called ");
}
@Override
public void method5() {
System.out.println("method5 called ");
}
} package interfaceadapter;
public class ImplementClass2 extends AbstractClass {
@Override
public void method2() {
System.out.println("method2 called");
} @Override
public void method4() {
System.out.println("method4 called");
}
}
测试类-客户角色
package interfaceadapter;
public class Test {
public static void main(String[] args) {
Interfaces class1 = new ImplementClass1();
Interfaces class2 = new ImplementClass2();
class1.method1();
class1.method2();
class1.method3();
class1.method4();
class1.method5();
System.out.println("------");
class2.method1();
class2.method2();
class2.method3();
class2.method4();
class2.method5();
}
}
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082756826-1153283698.png)
双向适配器
目标接口/目标实现类
package doubleadapter;
public interface TargetInterface {
void targetRequest();
} package doubleadapter;
public class TargetImplClass implements TargetInterface{
@Override
public void targetRequest() {
System.out.println("targetRequest ... ");
}
}
被适配者接口/被适配者实现类
package doubleadapter;
public interface AdapteeInterface {
void adapteeRequest();
} package doubleadapter;
public class AdapteeImplClass implements AdapteeInterface{
@Override
public void adapteeRequest() {
System.out.println("adapteeRequest ... ");
}
}
适配器
package doubleadapter;
public class Adapter implements TargetInterface,AdapteeInterface {
private TargetInterface target;
private AdapteeInterface adaptee;
Adapter(TargetInterface target){
this.target = target;
} Adapter(AdapteeInterface adaptee){
this.adaptee = adaptee;
}
@Override
public void adapteeRequest() {
target.targetRequest();
}
@Override
public void targetRequest() {
adaptee.adapteeRequest();
}
}
Client 客户端角色
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082757229-864433333.png)
适配器Adapter模式的宗旨是:
保留现有类所提供的服务,向客户提供接口,以满足客户的期望,也就是将现有接口转换为客户希望的另外的一个接口
本质在于转换
|
JDK中的小应用
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082757566-1343439641.png)
![](https://img2018.cnblogs.com/blog/897393/201809/897393-20180906082757868-651856320.png)
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.apache.commons.collections.iterators;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
public class EnumerationIterator implements Iterator {
private Collection collection;
private Enumeration enumeration;
private Object last; public EnumerationIterator() {
this((Enumeration)null, (Collection)null);
}
public EnumerationIterator(Enumeration enumeration) {
this(enumeration, (Collection)null);
} public EnumerationIterator(Enumeration enumeration, Collection collection) {
this.enumeration = enumeration;
this.collection = collection;
this.last = null;
} public boolean hasNext() {
return this.enumeration.hasMoreElements();
} public Object next() {
this.last = this.enumeration.nextElement();
return this.last;
} public void remove() {
if (this.collection != null) {
if (this.last != null) {
this.collection.remove(this.last);
} else {
throw new IllegalStateException("next() must have been called for remove() to function");
} } else {
throw new UnsupportedOperationException("No Collection associated with this Iterator");
}
} public Enumeration getEnumeration() {
return this.enumeration;
} public void setEnumeration(Enumeration enumeration) {
this.enumeration = enumeration;
}
}
public class EnumerationIterator implements Iterator {
private Enumeration enumeration;
|
设计模式是作为解决问题或者设计类层级结构时的一种思维的存在,而不是公式一样的存在!
|
适配器模式 adapter 结构型 设计模式(九)的更多相关文章
- 设计模式06: Adapter 适配器模式(结构型模式)
Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...
- 桥接模式 桥梁模式 bridge 结构型 设计模式(十二)
桥接模式Bridge Bridge 意为桥梁,桥接模式的作用就像桥梁一样,用于把两件事物连接起来 意图 将抽象部分与他的实现部分进行分离,使得他们都可以独立的发展. 意图解析 依赖倒置原 ...
- 享元模式 FlyWeight 结构型 设计模式(十五)
享元模式(FlyWeight) “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...
- 代理模式 PROXY Surrogate 结构型 设计模式(十四)
代理模式 PROXY 别名Surrogate 意图 为其他的对象提供一种代理以控制对这个对象的访问. 代理模式含义比较清晰,就是中间人,中介公司,经纪人... 在计算机程序中,代理就表示一个客户端不想 ...
- 组合模式 合成模式 COMPOSITE 结构型 设计模式(十一)
组合模式(合成模式 COMPOSITE) 意图 将对象组合成树形结构以表示“部分-整体”的层次结构. Composite使得用户对单个对象和组合对象的使用具有一致性. 树形结构介绍 为了便于理解, ...
- 享元模式/Flyweight模式/对象结构型/设计模式
flyweight 享元模式(对象结构型) Flyweight在拳击比赛中指最轻量级,即"蝇量级"或"雨量级",这里选择使用"享元模式"的意 ...
- 12、Decorator 装饰器 模式 装饰起来美美哒 结构型设计模式
1.Decorator模式 装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式(Decorator Pattern)允许向一个现 ...
- 11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式
1.Composite模式定义 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这 ...
- 结构型设计模式之适配器模式(Adapter)
结构 意图 将一个类的接口转换成客户希望的另外一个接口.A d a p t e r 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 适用性 你想使用一个已经存在的类,而它的接口不符合你 ...
随机推荐
- Error: Unable to access xxx.jar
在cmd中运行java -jar xxx.jar出现如下错误: Error: Unable to access xxx.jar 解决方法: 使用绝对路径:java -jar D:\Program Fi ...
- [bzoj1059]矩阵游戏
虽然是一道水难题,但是我这种蒟蒻还是要讲一讲的. Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N *N黑白方阵进行(如同国际 ...
- 编写输出“Hello world”
1.打开Eclipse---->点击文件 如图所示: 2. 然后在新建--->点击Java项目会出现下图框------>在项目名输入框中输入项目名并选择JRE----->点 ...
- [编译] 4、在Linux下搭建nRF51822的开发烧写环境(makefile版)
星期日, 09. 九月 2018 07:51下午 - beautifulzzzz 1.安装步骤 1) 从GNU Arm Embedded Toolchain官网下载最新的gcc-arm工具链,写文章时 ...
- idea中@Data标签getset不起作用
spring cloud中使用@Data标签,不用手动添加get set方法,但是如果项目中其他类中使用getset方法,如果报错,原因是idea中没有添加Lombok插件,添加上插件便可以解决.截图 ...
- 【安富莱专题教程第4期】SEGGER的J-Scope波形上位机软件,HSS模式简单易用,无需额外资源,也不需要写目标板代码
说明:1.在实际项目中,很多时候,我们需要将传感器或者ADC的数值以波形的形式显示.通常的解决办法是用串口上位机,USB接口上位机或者MDK的逻辑分析仪功能,使用这三种方式都比较繁琐.本期专题为大家讲 ...
- FFmpeg 结构体学习(八):FFMPEG中重要结构体之间的关系
FFMPEG中结构体很多.最关键的结构体可以分成以下几类: 解协议(http,rtsp,rtmp,mms) AVIOContext,URLProtocol,URLContext主要存储视音频使用的协议 ...
- [Swift]LeetCode319. 灯泡开关 | Bulb Switcher
There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every ...
- [Swift]LeetCode406. 根据身高重建队列 | Queue Reconstruction by Height
Suppose you have a random list of people standing in a queue. Each person is described by a pair of ...
- [Swift]LeetCode617. 合并二叉树 | Merge Two Binary Trees
Given two binary trees and imagine that when you put one of them to cover the other, some nodes of t ...