设计模式之适配器

适配器模式

 

适配器(Adapter)模式也称Wrapper模式,Wrapper有“包装器”的意思,就像用精美的包装纸将普通的商品包装成礼物那样,替我们把某样东西包装起来,使其能够用于其他用途的东西被称为“适配器”或是“包装器”。

在我们程序中,经常会存在现有的程序无法直接使用,需要做适当的变换后才能使用的情况。用于填补“现有的程序”和“所需的程序”之间差异的设计模式就是适配器。

 

举个栗子

左边是一台笔记本,右边是一个家庭电源,我们都知道,家庭电源是220V的交流电压,而笔记本工作的电压是12V直流电,那么如何如笔记本正常工作呢?通常,我们会用到AC适配器,将家庭用的220V交流电转化成我们所需要的直流12V电压。这就是适配器的工作,它位于实际情况和需求之间,填补两者之间的差异。

适配器模式有以下两种:

  • 类适配器模式(使用继承的适配器)

  • 2.对象适配器模式(使用委托的适配器)

 

使用继承的适配器

 

Banner类

package adapter;

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+"*");
    }
}

目前Banner类(Banner有广告横幅的意思)中,有将字符串用括号括起来的showWithParen()方法,和将字符串用*号括起来的showWithAster()方法。我们假设这个Banner类类似于前文中的“交流电220V”现有的程序”。

 

Print接口

package adapter;

public interface Print {

    public abstract void printWeek();
    public abstract void printStrong();
}

 

Print中有两个抽象方法,printWeek()和printStrong()。我们假设这个接口类似于前文中的“直流电12V”的“所需程序”。

现在需要做的事情是使用Banner类编写一个实现了Print接口的类,也就是说要做一个“交流电220V”转换成“直流电12V”的适配器。

需求:通过Print类的printWeek()和printStrong()输出(Hello)和*Hello*

 

PrintBanner类

package adapter;

public class PrintBanner extends Banner implements Print{

    public PrintBanner(String string) {
        super(string);
        
    }

    @Override
    public void printWeek() {
        super.showWithParen();
        
    }

    @Override
    public void printStrong() {
        super.showWithAster();
        
    }

}

 

PrintBanner扮演适配器这角色,该类继承了Banner类并实现了Print接口。PrintBanner类使用了showWithParent方法实现了printWeek,使用showWithAster方法实现了printStrong。这样,PrintBanner类就具有了适配器的功能了。

 

Main类

 

package adapter;

//使用继承的适配器
public class Main {
	public static void main(String[] args) {
		Print print=new PrintBanner("hello");
		print.printWeek();
		print.printStrong();
	}
}

Main类的作用是通过适配器角色的PrintBanner类来输出指定字符串格式。

运行结果:

(hello)
*hello*

请注意,这里我们将PrintBanner类的实例保存在了Print类型的变量中。在Main类中,我们是使用Print接口调用printWeek方法和printStrong方法来进行编程的。对于Main类的代码而言,Banner类的showWithParent方法和showWithAster方法被完全隐藏起来了。这就好像笔记本电脑只要在直流电12V下就能正常工作,但它并不知道这12V的电压是由适配器将220V交流电转化成的。

 

使用委托的适配器

 

“委托”通俗点讲就是“交给其他人”。比如,当我们无法出席一个重要会议时,可以写一份委任书,说明一下“我无法出席会议,安排XXX代我出席”。委托和委任的意思是一样的。在Java语言中,委托就是指将某个方法中的实际处理交给其他实例的方法。

 

Banner类

package adapter2;

public class Banner {

	private String string;
	public Banner(String string){
		this.string=string;
	}
	
	public void printWithParen(){
		System.out.println("("+string+")");
	}
	public void printWithAster(){
		System.out.println("*"+string+"*");
	}
}

在这Banner类内容没有任何改变。

 

Print抽象类

package adapter2;

public abstract class Print {

	public abstract void printWeek();
	public abstract void printStrong();
}

这里需要注意一点,Print不再是个接口,而是变成了一个抽象类。其中,Print中有两个抽象方法没有变,仍然是printWeek()和printStrong()。

 

PrintBanner类

package adapter2;

public class PrintBanner extends Print {
	private Banner banner;
	public PrintBanner(String string){
		banner=new Banner(string);
	}
	@Override
	public void printWeek() {
		banner.printWithParen();
		
	}
	@Override
	public void printStrong() {
		banner.printWithAster();
	}
}

PrintBanner类的banner字段中保存了Banner类的实例。该实例是在PrintBanner类的构造函数中生成的。然后,printWeek方法和printStrong方法会通过banner字段调用Banner类的showWithParent和showWithAster方法。

与之前的使用继承适配器调用父类中继承的showWithParent和showWithAster方法不同,这次我们通过字段来调用这两个方法。

这样就形成了一种委托关系,当PrintBanner类的printWeek被调用时,并不是PrintBanner类自己进行处理,而是将处理交给了Banner实例的showWithParent方法。

 

Main类

package adapter2;

//使用委托的适配器
public class Main {
	public static void main(String[] args) {
		Print print=new PrintBanner("hello");
		print.printWeek();
		print.printStrong();
	}
}

Main类和之前的也完全一样。

运行结果:

(hello)
*hello*

 

适配器模式中的角色

 

在适配器模式中有以下角色。

  • Target(对象)

该角色负责定义所需的方法。即让笔记本电脑正常工作所需的直流12V电。在程序中,由Print扮演此角色。

  • Client(请求者)

该角色负责使用Target角色所定义的方法进行具体处理。即12V直流电所驱动的笔记本电脑。在程序中,由Main类扮演此角色。

  • Adaptee(被适配)

Adaptee是一个持有既定方法的角色。即交流电220V。由Banner扮演此角色。

  • Adapter(适配)

Adapter角色的方法来满足Target角色的需求,这是Adapter模式的目的,也是Adapter角色的作用。Adapter角色就是将交流电220V转换成直流电12V的适配器。在程序中,由PrintBanner类扮演此角色。

 

什么时候使用Adapter模式

 

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

Adapter模式会对现有的类进行适配,生成新的类。通过该模式可以很方便地创建我们需要的方法群。当bug出现时,我们明确的知道bug不在现有的类中,所以我们只需调查扮演Adapter角色的类即可。

当Adapter角色和Target角色功能完全不同时,Adapter模式是无法使用的。就像我们无法用220V的交流电压让自来水出水一样。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值