前言:
来源于《head first 设计模式》。当作读书笔记了,这次看的是第7章适配器模式以及外观模式。先从适配器模式再到外观模式。
适配器模式的概念
将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无限。
适配器模式的uml图
- Client:用户类,使用新接口Target来完成某些特定的需求。
- Target:新的接口类,开放特定接口request来完成某些特定操作。
- Adaptee:被适配者,原有的类,即需要适配的类或适配者类。
- Adapter:适配器类,将Adaptee中的接口封装成Target中的新接口,来满足用户类的需求
其实就是Client调用Adapter实例的操作,Adapter委托给Adaptee来完成这些被调用的操作。
例子:
还是鸭子。有个人想吃鸭子,但是呢我们没有鸭子,只有火鸡,我们想用火鸡伪装成鸭子来卖给他,然而火鸡的接口不同,我们不能公然拿来冒充鸭子啊。那么适配器就来了。
Duck接口—Target
public interface Duck {
public void quack();
public void fly();
}
开放quack fly方法来让适配器适配
火鸡接口
public interface Turkey {
public void gobble();
public void fly();
}
火鸡类—Adaptee
public class WildTurkey implements Turkey {
public void gobble() {
System.out.println("Gobble gobble");
}
public void fly() {
System.out.println("I'm flying a short distance");
}
}
最终的执行者
适配器–adapter
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
public void fly() {
turkey.fly();
}
}
采用组合的方式,将最终执行委托给火鸡对象。
最终调用代码—client
public class TurkeyTestDrive {
public static void main(String[] args) {
WildTurkey wildTurkey = new WildTurkey();
Duck duckAdapter = new TurkeyAdapter(wildTurkey);
System.out.println("The DuckAdapter says...");
duckAdapter.quack();
duckAdapter.fly();
}
}
这里就适配成功了,用户调用的还是鸭子的quack方法以及fly方法,但其实背后实现的却是一只火鸡。成功的偷龙转凤。适配器模式有一个好处就是如果一段时间后,我们的火鸡有了新的接口,我们不需要修改客户认知鸭子的方法,只需要修改适配器代码即可。还有一个好处就是被适配者的任何子类都可以搭配者适配器使用,即火鸡的子类绿毛火鸡,也会被适配器适配成鸭子。
上述的是对象适配器,还有一种是类适配器,但是java无法实现噢,因为其需要多继承才可以实现,书上是这样说但是我觉得Target是接口啊,继承adaptee然后实现Target接口不是冲突的。
两者的不同之处在于类适配器继承了Target与Adaptee。而对象适配器利用组合的方式将请求传送给被适配者。
与其他设计模式的不同
装饰者模式vs适配器模式
装饰者:会拓展包装类的行为或者责任,而不是简单的传送
适配器:只是转换接口调用,将任务委托给被适配者
外观模式
外观模式的概念
提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用
这个模式仅仅是提供了一层封装,让原本很多个步骤的工作简化为一步。举个例子就是早上刷牙,有一下几个步骤挤牙膏,刷牙齿,漱口。而人呢嫌太麻烦不想每次都需要写三个方法,直接在大脑中把三个动作封装成刷牙一个方法。刷牙包括了上述三个动作。即以后人只需要调用大脑的刷牙即可完成。
外观模式不只是简化了接口,也将客户从组件的子系统中解耦出来。(即人可以不再管手挤牙膏,漱口。交给大脑来做了,只需调用刷牙方法)