上一篇博客说完了 java 23 中设计模式中的五种 创建性模式,由于篇幅过长,新开一贴今天开始学习结构型模式,

结构型模式包括以下七种:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

这里有也很详细的讲解:适配器模式

先学习适配器模式,适配器模式包括,类的适配器模式,对象的适配器模式,接口的适配器模式;其中对象的适配器模式是各种构造型模式的起源,见下图:

一:适配器模式

  定义:将一个类的接口转换为用户希望的另一个接口,适配器模式让一些接口不兼容的类可以一起工作

  适配器配器就是一种适配中间件,他存在于不匹配的二者之间,用于连接二者,将不匹配不匹配变得匹配,简单点理解就是平常缩减的转接头,转换器之类的等

  适配器模式有如下三种:类适配器、对象适配器、接口适配器;

  类适配器和对象适配器区别不大没作用一样,接口适配器差别较大。

  1:类适配器模式

        

  当我们在接口A中没有我们想要的方法,却在另一个接口B中发现了合适的方法,我们又不能改变访问接口A,在这种情况下,我们可以定义一个适配器P来进行中转,这个适配器P要实现我们访问的接口A,这样我们就能继续访问当前接口A中的方法(虽然我们目前还不需要),然后在继承接口B的实现类BB,这样我们就可以在适配器P中访问接口B的方法了,这是我们在适配器P中的接口A方法中直接饮用BB中的方法,这样就完成了一个简单的类适配器。

  不是自己的话还是不好理解,这里我又翻了几篇博客以加深理解,https://www.cnblogs.com/yueguanguanyun/p/7985411.html ;

  类适配器大致是:如果需要客户端需要实现一个接口,but,这个接口中的方法并不能满足你的全部需求,你还需要另外一个接口或类中的方法,这是我们就可以使用一个适配器在实现原接口的基础上去继承所需要添加接口的实现类或直接继承某个类。我看到这里的时候有点蒙蔽,不就是一个类需要两个接口的方法吗,直接实现两个借口不就好了吗?为什么要那么麻烦呢?搜遍全网也没遇见解答,看来是我的脑回路太奇葩了,不过既然有问题就得去疏通它,于是...写了两个接口试验一下,事实证明实践出真知。下面看一下代码就明白了:

/**
* 接口 1
*/
public interface Interface1 {
void method1();
} /**
* 接口 2
*/
public interface Interface2 {
void method2();
} /**
* 实现类 直接实现接口1 和接口2的方法
*/
public class Impl1 implements Interface1,Interface2 {
@Override
public void method1() {
System.out.println("method1");
} @Override
public void method2() {
System.out.println("method2");
}
} /**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Interface1 inter1 = new Impl1();
Interface2 inter2 = new Impl1();
inter1.method1();
inter2.method2();
}
}

  看到测试类估计很多有疑问的小伙伴们都要恍然大悟了(或许很多小伙伴们本来就没有疑问),对的,一个实现类实现两个接口之后,用该接口的实例只能去调用属于该接口的方法。我们需要的是用一个接口的实例去调用其它接口的方法,于是适配器模式之类适配器闪亮登场:我还是先滚去写代码。。。

  我有两个接口,业务上需要实现Source源接口,但是还需要target接口的方法,客户端通过Source接口实例可以调用两个接口的方法

/**
* 源接口
*/
public interface Source {
void sourceMethod1();
} /**
* 目标接口
*/
public interface Target {
void targetMethod();
}

  我们既然想扩展Target接口的方法,那么我们先实现该接口

 public class TargetImpl implements  Target{
@Override
public void targetMethod() {
System.out.println("Target 目标接口的方法");
}
}

  怎么让两个接口实现适配呢,这时就可以创建适配器类,先继承要扩展的目标接口的实现类,然后再实现我们本来需要实现的接口,(简单说即先继承再实现),在方法中调用目标接口的方法,因为继承了Target的实现类所以可以直接调用。代码如下

 /**
* 类适配器
*/
public class Adapter extends TargetImpl implements Source{
@Override
public void sourceMethod1() {
//调用目标接口的方法
targetMethod();
}
}

  测试类

/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Source source = new Adapter();
source.sourceMethod1();
}
}

  结果输出:Target 目标接口的方法

  如果想要同时调用Source接口和Target接口的方法,需要在Source中添加一个和Target中方法一直的抽象方法,如下:

 /**
* 源接口
*/
public interface Source {
void sourceMethod1(); /*新接口的方法*/
void targetMethod();
}

  适配器只需要实现源接口的方法

/**
* 类适配器
*/
public class Adapter extends TargetImpl implements Source{
@Override
public void sourceMethod1() {
System.out.println("Source 源接口的方法");
}
}

  测试类

/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
Source source = new Adapter();
source.sourceMethod1();
source.targetMethod();
}
}

  输出结果:

Source 源接口的方法
Target 目标接口的方法

  这样我们就在Source 接口中使用Target接口的方法;

  总结:类适配器模式即是通过继承来实现适配器的功能;

  2:对象适配器模式

  对象适配器是指通过合成复用来实现适配器功能;基本思路与类适配器相同:这里在理一下哈,有一个源接口Source和目标接口Target,客户端必须实现Source接口的时候如何使用Source接口的实例调用Target接口的方法呢,类适配器其中我们使用了继承的方法继承了Target接口的实现类,对象适配器的基本思想差不多,只不过是把继承改为了在适配器中创建Target的实例变量,并为该变量创建构造器用于为该变量赋值。就可以通过实例变量来调用Target的方法了。结合代码看一下(代码纯属手敲,望支持):

  老规矩先上两个接口:Source(接口),和Target接口

 /**
* 源接口
*/
public interface Source {
/**Source接口的方法*/
void sourceMethod();
} /**
* 目标接口
*/
public interface Target {
/**target接口的方法*/
void targetMethod();
}

  我们想另外调用target接口,所以先给它来个实现类吧:

 /**
* Target接口实现类
*/
public class TargetImpl implements Target {
@Override
public void targetMethod() {
System.out.println("Target接口的方法");
}
}

  对象适配器类:

package com.shipeiqi.duixiangshipeiqi;

/**
* 对象适配器
*/
public class Adapter implements Source{ /* 1:对象适配器在适配器中实现必须的接口
* 2:把需要引用的接口作为适配器类的成员变量,
* 3:创建带参构造方法
*/
private Target target; public Adapter(Target target) {
this.target = target;
} @Override
public void sourceMethod() {
System.out.println("Source接口的方法");
} /**
* 在这里调用目标接口的方法
*/
@Override
public void targetMethod() {
target.targetMethod();
}
}

  测试类:

 public class Test {
public static void main(String[] args) {
/**传入目标接口的实现类,给适配器中的成员变量赋值*/
Source source = new Adapter(new TargetImpl());
source.sourceMethod();
source.targetMethod();
}
}

  输出结果:

Source接口的方法
Target接口的方法

  总结:对象适配器模式即是通过合成复用来实现适配器的功能;

  3:接口适配器模式

  接口适配器模式也很好理解,在大部分情况下我们写的一个接口中会有很多很多很多的抽象方法,当我们写接口的实现类时必须要实现该接口的所有抽象方法,,而我们可能只需要其中的一个方法,这样就会使该实现类变得十分臃肿,从而造成了资源的浪费;为了解决这个问题,我们可以引用适配器模式,借助于一个抽象类(即适配器类),该抽象类实现了所有的接口,我们不和原始的接口打交道,只和该抽象类取得联系,我们写一个类继承该抽象类,然后实现需要的方法即可;代码如下:

  原始接口

 /**
* 有很多方法的接口
*/
public interface Source {
void method();
void method1();
void method2();
void method3();
void method4();
void method5();
void method6();
}

  抽象类实现接口的方法

 /**
* 接口适配器
* 抽象类实现接口,实现接口的方法,然后自定义业务类只需要继承该抽象类,重写所需的方法即可
*/
public abstract class Adapter implements Source{
public void method(){}
public void method1(){}
public void method2(){}
public void method3(){}
public void method4(){}
public void method5(){}
public void method6(){}
}

  写个类继承抽象类,只重写需要的方法即可

public class Service extends Adapter {
@Override
public void method(){
System.out.println("这个是我需要的方法");
}
}

  测试类:

public class Test {
public static void main(String[] args) {
Service service = new Service();
service.method();
}
}

  结果:

这个是我需要的方法

  4:总结

  总的来说适配器模式还是比较容易理解的,下面说一下三种适配器模式的使用场景和优缺点:

  类的适配器模式:当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

  对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Adapter类,持有原类的一个实例,在Adapter类的方法中,调用实例的方法就行。

  接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Adapter,实现所有方法,我们写别的类的时候,继承抽象类即可。

  适配器模式的优缺点:

  优点:

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

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

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

  缺点:

    1:一次最多只能适配一个适配者类,不能同时适配多个适配者。

    2:适配者类不能为最终类,在C#中不能为sealed类

    3:目标抽象类只能为接口,不能为类,其使用有一定的局限性。

java设计模式自我总结---适配器模式的更多相关文章

  1. 重学 Java 设计模式:实战适配器模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...

  2. Java设计模式系列之适配器模式

    适配器模式的定义 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.(就类似于我们充电器的转接头将220V的电压转换成我们的手机端 ...

  3. Java设计模式7:适配器模式

    适配器模式 适配器模式说的是,可以把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类可以一起工作. 适配器模式的用途 适配器模式的用途,在网上找了一幅图,挺形象 ...

  4. java设计模式笔记(1)-适配器模式

    适配器的定义 适配器就是一个接口转换器,它可以是一个独立的硬件接口设备,允许硬件或电子接口与其它硬件或电子接口相连,也可以是信息接口.比如:电源适配器.三角架基座转接部件.USB与串口的转接设备等. ...

  5. java 设计模式-缺省适配器模式

    本文转载地址:http://www.cnblogs.com/iyangyuan/archive/2013/03/11/2954808.html 在程序设计过程中,读者很可能遇到这样一种困境:设计了一个 ...

  6. JAVA设计模式初探之适配器模式

    http://blog.csdn.net/jason0539/article/details/22468457 1. 概述 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接 ...

  7. Java设计模式学习记录-适配器模式

    前言 之前已经将五个创建型设计模式介绍完了,从这一篇开始介绍结构型设计模式,适配器模式就是结构型模式的一种,适配器要实现的效果是把“源”过渡到“目标”. 适配器模式 在开发过程中,使用一个已经存在的类 ...

  8. JAVA设计模式初探之适配器模式(转)

    1. 概述 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 解决的问题 即Adapter模式使得原本由于接口不兼容而不 ...

  9. 【java设计模式】-07适配器模式

    适配器模式 定义: 将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 类型: 结构型模式 应用实例: 1.JAVA JDK 1.1 提供 ...

随机推荐

  1. Ajax 简单的实例代码

    <!DOCTYPE HTML><html><head><script src="http://libs.baidu.com/jquery/2.0.0 ...

  2. springboot jpa 复合主键

    https://blog.csdn.net/wyc_cs/article/details/9031991 创建一个复合主键类 public class LevelPostMultiKeysClass ...

  3. JarvisOJ Misc shell流量分析

    分析一下shell流量,得到flag 看着一大推的数据记录头都大了,并没有什么wireshark的使用经验,开始胡搞 首先用notepad++打开,搜索flag字样找到了一个类似于python脚本的东 ...

  4. 笔记本装双系统!win10+Linux!所有的坑自己一个个爬过来,纪念一下。

    笔记本装双系统!win10+Linux!所有的坑自己一个个爬过来,纪念一下. 2018年09月16日 21:27:19 Corax_2ven 阅读数:14038   写在前面,装了大概5遍,装了删删了 ...

  5. BZOJ4269再见Xor——高斯消元解线性基

    题目描述 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. 输入 第一行一个正整数N. 接下来一行N个非负整数. 输出 一行,包含两 ...

  6. Django 模板系统

    Django模板系统 常用语法 {{}} 变量相关 {%%} 逻辑相关 变量 格式 {{ 变量名 }} 命名规则 包括任何字母数字以及下划线 ("_")的组合 变量名称中不能有空格 ...

  7. MySQL防止库存超卖方法总结

    订单超卖问题是涉及到库存项目的重中之重,这里我总结一下常用的方法 1.简单处理[update & select 合并](乐观锁) beginTranse(开启事务)$num = 1; try{ ...

  8. Django--ORM相关操作

    必知必会13条 <1> all(): 查询所有结果 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> get(**kwargs ...

  9. 信号(1): signal

    1. 头文件#include <signal.h> 2. 功能设置某一信号的对应动作 3. 函数原型void (*signal(int signum,void(* handler)(int ...

  10. SNMP学习——v3 VACM

    目录: ☆ SNMPv3视图访问控制模型    ☆ SNMPv3报文格式    ☆ VACM参数    ☆ Context Table    ☆ Security To Group Table     ...