适配器模式
定义:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
代码示例
旧系统使用接口A,现在接口升级,需求接口B。
1、旧接口
public interface InterfaceA {
void execute();
void undo();
}
2、旧接口实体类
public class ConcretedClassA implements InterfaceA {
@Override
public void execute() {
System.out.println("具体类A执行");
}
@Override
public void undo() {
System.out.println("具体类A撤销");
}
}
3、代码升级,采用接口B
public interface InterfaceB {
void executeB();
void undoB();
}
实现新的接口B举例:
public class ConcretedClassB implements InterfaceB {
@Override
public void executeB() {
System.out.println("具体类B执行");
System.out.println("具体类B执行");
}
@Override
public void undoB() {
System.out.println("具体类B撤销");
System.out.println("具体类B撤销");
}
}
4、编写适配器类(进行接口转换A->B)
public class AdapterA2B implements InterfaceB {
private InterfaceA interfaceA;
public AdapterA2B(InterfaceA interfaceA) {
this.interfaceA = interfaceA;
}
@Override
public void executeB() {
interfaceA.executeA();
interfaceA.executeA();
}
@Override
public void undoB() {
interfaceA.undoA();
interfaceA.undoA();
}
}
适配器,持有实现接口A的对象引用,利用内部代码转换成接口B的方法。从而让客户代码可以用该适配器对象(模拟实现接口B的对象)。
5、客户代码
public static void main(String[] args) {
InterfaceA a = new ConcretedClassA();
//现在客户需要使用接口B,但旧系统使用的是接口A,不希望改变旧接口
// 通过适配器可以将A包装成B
InterfaceB b = new AdapterA2B(a);
execute(b);
}
public static void execute(InterfaceB interfaceB) {
interfaceB.executeB();
interfaceB.undoB();
}
对于客户代码来说,execute方法只需要参数实现InterfaceB,通过适配器把A包装成B,进而可以使用。
说明
我们把接口A和接口B的变化封装在适配器内部。
类图
客户代码需求实现Target接口的类,而我们只有Adaptee类;使用适配器,把Adaptee封装成实现Target接口的类,从而客户代码可以间接使用Adaptee。
上述代码示例,Client就是Main函数,Target就是InterfaceB,Adapter是AdapterA2B,Adaptee是InterfaceA。
外观模式
定义:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。(类似于一键XX,一键开启之类的)
示例代码
public class AllFacade{
A a;
B b;
C c;
D d;
public AllFacade(A a,B b,C c,D d){
this.a=a;
this.b=b;
this.c=c;
this.d=d;
}
public void execute(){
a.execute();
b.execute();
c.execute();
d.execute();
}
//public void fun....
}
类图
说明
- 通过一个外观类(接口)将复杂的子系统操作过程,封装成简便的方法对外暴露,供客户使用起来比较方便。
- 外观将客户从一个复杂的子系统中解耦。
- 实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行。
适配器、外观、装饰者的区别
适配器:将一个接口转换成另一个接口以改变接口,为了兼容性和避免修改原有代码。
外观:将一群接口(类)包装成一个接口(类)以简化接口,为了客户使用方便。
装饰者:将一个对象包装起来以增加新的行为和责任。
设计原则
最少知识原则
只和你的密友谈话
这个原则希望我们在设计中,不要让太多的类耦合在一起,免得修改系统中的一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,它需要花许多成本去维护,也会因为太复杂而不容易被其他人了解。
指导方针
就任何对象而言,在该对象的方法内部,我们只应该调用属于以下范围的方法:
- 该对象本身
- 被当做方法的参数而传递进来的对象
- 此方法创建或实例化的任何对象
- 对象的任何组件(把“组件”想象成是被实例变量的引用的任何对象,换言之,把这想象成是“有一个”(HAS-A)关系)
举例
不采用原则的方法:
public float getTemp(){
Thermometer thermometer = station.getThermometer();
return thermometer.getTemperature();
}
采用原则的方法:
public float getTemp(){
return station.getTemperature();
}
采用原则的一个类:
public class Car{
Engine engine; //组件
public Car(){}
public void start(Key key){ //被当做参数传进来的对象,其方法可以调用
Doors doors = new Doors() //创建新的对象,它的方法可以被调用
boolean authorized = key.turns();//被当做参数传进来的对象,其方法可以调用
if(authorized){
engine.start(); //可以调用组件的方法
updateDashboardDisplay();//可以调用同一个对象内的本地方法
doors.lock();//可以调用创建或实例化的对象的方法
}
}
public void updateDashboardDisplay(){}
}