适配器模式
适配器模式(Adapter Pattern)又叫做变压器模式。
定义
将一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。
适配器模式涉及以下三个角色:
- 目标(Target)角色:该角色定义要转换成的目标接口。
- 源(Adaptee)角色:需要被转换成目标角色的源角色。
- 适配器(Adapter)角色:该角色是适配器模式的核心,其职责是通过继承或是类关联的方式,将源角色转换成目标角色。
应用
- 优点:
1)适配器模式可以让两个没有任何关系的类在一起工作
2)增加类的透明性
3)提高类的复用性
4)增加代码的灵活性 - 缺点:
1)过多地使用适配器,会让系统非常零乱,不易整体进行把握。
2)由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。 - 使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。
实例
水饺转换成馄饨
水饺是Adaptee
ShuiJiao.java
public class ShuiJiao{
public void makeshuijiao(){
System.out.println("调制菜馅");
System.out.println("擀面皮");
System.out.println("包饺子");
}
}
馄饨是Target
Hundun.java
public interface Hundun{
public void makeHundun();
}
FoodAdapter.java
public class FoodAdapter extends ShuiJiao implements Hundun{
public void makeHundun(){
super.makeShuiJiao();
System.out.println("馄饨和水饺一样是以面包馅的食品");
}
}
ClientDemo.java
public class ClientDemo{
public static void main(String args[]){
Hundun h=new FoodAdapter();
h.makeHundun();
}
}
运行结果如下所示
调制菜馅
擀面皮
包饺子
馄饨和水饺一样是以面包馅的食品
外观模式
外观模式(Façade Pattern)也叫门面模式。
定义
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供一个高层次的接口,使得子系统更易使用。
外观模式具有以下两个角色:
- 外观(Facade)角色:客户端可以调用该角色的方法,该角色知晓相关子系统的功能和责任。正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统,即该角色没有实际的业务逻辑,只是一个委托类。
- 子系统角色:可以同时有一个或多个子系统,每一个子系统都不是一个单独的类,而是一个类的集合。子系统不知道外观角色的存在,对于子系统而言,外观角色仅仅是另一个客户端而已。
应用
- 优点:
1)减少系统的相互依赖,所有的依赖都是对Facade对象的依赖,与子系统无关。
2)提高灵活性。
3)提高安全性,Facade中未提供的方法,外界无法访问。 - 缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
- 使用场景:
1)为一个复杂的模块或子系统提供一个供外界访问的接口。
2)子系统相对独立,外界对子系统的访问只要黑箱操作即可。
3)预防风险扩散,使用Facade进行访问操作控制。
实例
使用外观模式模拟秘书为老板准备工作的过程。
Airpot.java
public class Airpot{
public void bookTicket(String from,String to){
System.out.println("订购了从"+from+"到"+to+"的机票");
}
}
Restaurant.java
public class Restaurant{
public void reserve(int num){
System.out.println("订了一桌"+num+"个人的酒席");
}
}
Hotel.java
public class Hotel{
public void reserve(int days){
System.out.println("订了"+days+"天的房间");
}
}
Chauffeur.java
public class Chauffer{
public void drive(String to){
System.out.println("司机开车去"+to);
}
}
Secretary.java
public class Secretary{
private Chauffeur chauffeur=new Chauffeur();
private Hotel hotel=new Hotel();
private Restaurant restaurant=new Restaurant();
private Airpot airpot=new Airpot();
//安排出差
public void trip(Stirng to,int days){
airpot.bookTicket("青岛",to);
chauffer.drive("机场");
hotel.reserve(days);
}
//安排饭局
public void repast(int num){
restaurant.reserve(num);
chauffer.drive("酒店");
}
}
Boss.java
public class Boss{
public static void main(String[] args){
Secretary s=new Secretary();
System.out.println("老板告诉秘书要到上海出差10天");
s.trip("上海",10);
System.out.println("--------");
System.out.println("老板告诉秘书要请8个人吃饭");
s.repast(8);
}
}
运行结果如下。
老板告诉秘书要到上海出差10天
订购了从青岛到上海的机票
司机开车去机场
订了10天的房间
--------
老板告诉秘书要请8个人吃饭
订了一桌8个人的酒席
司机开车去酒店