chapter07_随遇而安——适配器模式和外观模式
-
(1) 适配器的作用
将一个接口转换成另一个接口
(2) 使用适配器的过程
1° 客户通过目标接口调用适配器的方法
2° 适配器使用 被适配者 的接口, 将请求转换成被适配器的一个或多个调用接口
__实现了调用者和被适配者的解耦__
(3) 示例
Duck.java
public interface Duck {
void quack();
void fly();
}
Turkey.java
public interface Turkey {
void gobble();
void fly();
}
TurkeyAdapter.java
public class TurkeyAdapter implements Duck {
private Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
public void fly() {
for (int i = 0; i < 5; i++) {
turkey.fly();
}
}
}
Turkey和Duck是两个不同的接口, TurkeyAdapter构造器注入一个turkey对象, 将Duck的行为映射成内部turkey对象的行为
-
适配器模式
将一个类的接口, 转换成客户期望的另一个接口, 适配器让原本接口不兼容的类可以合作无间
-
适配器的实际应用例子
以前的Enumeration接口转换为现在的Iterator接口
public class EnumerationIterator implements Iterator<Object> { private Enumeration<?> enumeration; public EnumerationIterator(Enumeration<?> enumeration) { this.enumeration = enumeration; } public boolean hasNext() { return enumeration.hasMoreElements(); } public Object next() { return enumeration.nextElement(); } public void remove() { throw new UnsupportedOperationException(); } }
EnumerationIterator内部包含一个Enumeration对象, 将hasNext和next方法委托之;
由于Enumeration是一个只读接口, 所以调用remove()时抛出UnsupportedOperationException异常
-
装饰器模式和适配器模式的对比
装饰器模式不会改变接口, 它的目标是将新的行为添加到类中;
适配器模式的作用是改变接口类型
-
(1) 外观模式
实现一个提供更合理的接口的外观类, 从而将一个复杂的子系统变得容易使用
(2) 外观模式可以理解为
一个适配器包装多个被适配者
(3) 示例
HomeTheaterFacade.java
public class HomeTheaterFacade { private Amplifier amp; private Tuner tuner; private DvdPlayer dvd; private CdPlayer cd; private Projector projector; private TheaterLights lights; private Screen screen; private PopcornPopper popper; public HomeTheaterFacade( Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen, TheaterLights lights, PopcornPopper popper) { this.amp = amp; this.tuner = tuner; this.dvd = dvd; this.cd = cd; this.projector = projector; this.screen = screen; this.lights = lights; this.popper = popper; } public void watchMovie(String movie) { System.out.println("Get ready to watch a movie..."); popper.on(); popper.pop(); lights.dim(10); screen.down(); projector.on(); projector.wideScreenMode(); amp.on(); amp.setDvd(dvd); amp.setSurroundSound(); amp.setVolume(5); dvd.on(); dvd.play(movie); } ... }
Amplifier, Tuner, DvdPlayer等都是内部的被适配者, watchMovie有着复杂的流程, 需要各个子系统协同操作;
HomeTheaterFacade提供了统一的接口方法watchMovie(), 使得函数调用更加友好
(4) 外观模式使得客户实现从任何子系统中解耦
-
外观模式和适配器模式的区别
意图不同!!!
适配器模式的意图是改变接口以迎合客户的需求;
外观模式的意图是简化接口
-
外观模式
提供了一个统一的接口, 用来访问子系统中的一群接口。外观模式定义了一组高层接口, 让子系统更容易使用
-
(1) 设计原则: 最少知识原则
减少对象之间的交互, 只留下几个"密友"对象, 不要让太多的类耦合在一起
(2) 具体操作方针
在某个对象的方法内, 我们只应该调用属于以下范围的方法:
1° 对象本身的方法
2° 被当作输入参数传进来的对象的方法
3° 方法内部创建的对象的方法
4° 对象的内部组件的方法
也就是说, 尽量不要在某个方法中出现
this.inner.getA().getX()
这种链式调用
(3) 完全遵循"最少知识原则"很可能会导致过度封装(为了防止出现(2)中的情况又包装了几个类), 造成复杂度和开发时间的增加, 所以应__在抽象和速度之间折中__