2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

时间:2023-03-09 18:04:47
2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

1、什么是适配器模式?

适配器如同一个常见的变压器,也如同电脑的变压器和插线板之间的电源连接线,他们虽然都是3相的,但是电脑后面的插孔却不能直接插到插线板上。

如果想让额定工作电压是直流12伏特的笔记本电脑在交流100伏特”的AC电源下工作,应该怎么做呢?通常,我们会使用AC适配器,将家庭用的交流100伏特电压转换成我们所需要的直流12伏特电压。这就是适配器的工作,它位于实际情况与需求之间,填补两者之间的差异。适配器的英文是Adapter,意思是.....相互适合的东西”。前面说的AC适配器的作用就是让工作于直流12伏特环境的笔记本电脑适合于交流100伏特的环境(如下图)。

2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

在程序世界中,经常会存在现有的程序无法直接使用,需要做适当的变换之后才能使用的情况。这种用于填补“现有的程序”和“所需的程序”之间差异的设计模式就是Adapter模式。Adapter模式也被称为Wrapper模式。Wrapper有 “包装器”的意思,就像用精美的包装纸将普通商品包装成礼物那样,替我们把某样东西包起来,使其能够用于其他用途的东西就被称为“包装器”或是“适配器”。

Adapter模式有以下两种。

●类适配器模式(使用继承的适配器) ●对象适配器模式(使用委托的适配器)

本章将依次学习这两种Adapter模式。

2、适配器样例

首先定义一个Banner类,比如就是我们实际的情况.

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:21
* @Description TODO
*/
public class Banner {    private String string;    public Banner(String string) {
       this.string = string;
  }    public void showWithParen() {
       System.out.println("(" + string + ")");
  }    public void showWithAster() {
       System.out.println("*" + string + "*");
  }
}

定义一个Print接口, 是需求的接口

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:24
* @Description TODO
*/
public interface Print {
   public abstract void printWeak();    public abstract void printStrong(); }

2.1、类适配器模式

定义一个PrintBanner类,扮演适配器的角色 它继承Banner并且实现Print接口.

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:25
* @Description TODO
*/
public class PrintBanner extends Banner implements Print {    public PrintBanner(String string) {
       super(string);
  }    @Override
   public void printWeak() {
       showWithParen();
  }    @Override
   public void printStrong() {
       showWithAster();
  }
}

Main测试类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:26
* @Description TODO
*/
public class Main1 {
   public static void main(String[] args) {
       PrintBanner p1 = new PrintBanner("hello world");
       p1.printWeak();
       p1.printStrong();
  }
}

运行结果如下:

(hello world)
*hello world*

2.2、对象适配器模式

定义一个BasePrint抽象类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020-07-14 11:24
* @Description TODO
*/
public abstract class BasePrint {
   public abstract void printWeak();    public abstract void printStrong(); }

定义一个PrintBanner2类,它继承BasePrint

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020/7/14 22:10
* @Description TODO
*/
public class PrintBanner2 extends BasePrint {
   Banner banner;    public PrintBanner2(String string) {
       this.banner = new Banner(string);
  }    @Override
   public void printWeak() {
       banner.showWithParen();
  }    @Override
   public void printStrong() {
       banner.showWithAster();
  }
}

定义Main2测试类

package cn.design.adapter;

/**
* @author lin
* @version 1.0
* @date 2020/7/14 22:11
* @Description TODO
*/
public class Main2 {
   public static void main(String[] args) {
       PrintBanner2 p2 = new PrintBanner2(" main2 ");
       p2.printWeak();
       p2.printStrong();
  }
}

运行结果如下:

( main2 )
* main2 *

3、适配器的登场角色

类适配器模式:

2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

对象适配器模式

2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

◆Target(对象)

该角色负责定义所需的方法。以本章开头的例子来说,即让笔记本电脑正常工作所需的直流12伏特电源。在示例程序中,由Print接口(使用继承时)和Print类(使用委托时)扮演此角色。

◆Client (请求者)

该角色负责使用Target 角色所定义的方法进行具体处理。以本章开头的例子来说,即直流12伏特电源所驱动的笔记本电脑。在示例程序中,由Main类扮演此角色。

◆Adaptee (被适配)

注意不是Adapt-er (适配)角色,而是Adapt-ee (被适配)角色。Adaptee是-一个持有既定方法的角色。以本章开头的例子来说,即交流100伏特电源。在示例程序中,由Banner类扮演此角色。如果Adaptee角色中的方法与Target角色的方法相同(也就是说家庭使用的电压就是12伏特直流电压),就不需要接下来的Adapter角色了。

◆Adapter (适配)

Adapter模式的主人公。使用Adaptee角色的方法来满足Target 角色的需求,这是Adapter 模式的目的,也是Adapter角色的作用。以本章开头的例子来说,Adapter 角色就是将交流100伏特电压转换为直流12伏特电压的适配器。在示例程序中,由PrintBanner类扮演这个角色。在类适配器模式中,Adapter角色通过继承来使用Adaptee角色,而在对象适配器模式中,Adapter角色通过委托来使用Adaptee角色。

4、什么时候使用适配器?

一定会有读者认为“如果某个方法就是我们所需要的方法,那么直接在程序中使用不就可以了吗?为什么还要考虑使用Adapter模式呢?”那么,究竟应当在什么时候使用Adapter模式呢?

很多时候,我们并非从零开始编程,经常会用到现有的类。特别是当现有的类已经被充分测试过了,Bug很少,而且已经被用于其他软件之中时,我们更愿意将这些类作为组件重复利用。

Adapter模式会对现有的类进行适配,生成新的类。通过该模式可以很方便地创建我们需要的方法群。当出现Bug时,由于我们很明确地知道Bug不在现有的类( Adaptee角色)中,所以只需调查扮演Adapter角色的类即可。这样一来, 代码问题的排查就会变得非常简单。

5、总结

个人经验

如何做到一个类不被实例化或者不被轻易实例化?

1.把一个类定义为抽象类;

2.把一个类的构造方法设置为:private类型的,这样在客户端就不能通过new ClassName()方法来轻易将一个类实例化,而要生成此类的实例就必须通过一个特殊的方法,这样在一个系统中,对此类的使用就能得到合理的控制(如:单例模式/多例模式/简单工厂方法等模式)。

3. 对于两个独立的系统,要满足ocp原则,则适配器模式会有一定的局限性。

发哥讲

2、适配器 adapter 模式 加个"适配器" 以便于复用 结构型设计模式

如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈~

● 扫码关注公众号