目录
一、基础概念
二、UML类图
三、角色设计
四、案例分析
五、总结
一、基础概念
外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
二、UML类图
三、角色设计
角色 | 描述 |
---|---|
外观角色 | 为多个子系统对外提供一个统一的接口,外观模式的核心,客户端可以调用这个接口实现对各个子系统的访问 |
子系统角色 | 实现系统的部分功能,客户可以通过外观角色访问它们,子系统对外界隐藏了内部的复杂性 |
客户端角色 | 通过一个外观角色访问各个子系统的功能,客户可以根据需要直接访问子系统类 |
四、案例分析
外观模式就像一个遥控器,它把许多电器的开关集中到了一个遥控器上,你只需要按遥控器上简单的按钮就可以控制电视、空调等电器开关。
1、电视、空调等电器就是不同的子系统。
2、遥控器是外观类,它将电视、空调的开关简单封装起来,提供了简单的接口(按钮)。
3、用户(客户端)只需要按遥控器的按钮,而不需要去操作每一个电器的开关。
4、如果需要替换一个新的电视,只要修改遥控器上的电视按钮对应代码,对客户端无影响。这样通过遥控器(外观类)把复杂的子系统简化和封装起来,用户就只需要操作简单的接口,大大降低了系统的复杂性。同时在修改子系统时,也只会影响外观类而不会影响到客户端。
总之,外观模式提供了一个简单入口来访问和使用复杂子系统,它对客户屏蔽了子系统组件,减少系统相互依赖,实现解耦。
假设现在有一个简单的例子:平日我们网上购物一般会分为4个步骤,挑选物品,添加购物车,填写收获信息和支付,下面我们就通过代码来实现上述功能。
定义一个网上购物的流程接口:
public interface PurchaseProcess {//挑选物品void pickGoods(String goodName);//添加到购物车void addCart(String goodName);//填写收货信息void addConsigneeInformation(String consigneeInformation);//支付void pay();}
购物接口对应的实现类:
public class PurchaseProcessImpl implements PurchaseProcess {@Overridepublic void pickGoods(String goodName) {System.out.println("挑选的商品:"+goodName);}@Overridepublic void addCart(String goodName) {System.out.println("将《"+goodName+"》添加到购物车!");}@Overridepublic void addConsigneeInformation(String consigneeInformation) {System.out.println("您填写的收货地址:"+consigneeInformation);}@Overridepublic void pay() {System.out.println("支付完成...");}
}
提供一个统一的方法进行购物:
public class Shopping {private PurchaseProcessImpl purchaseProcess = new PurchaseProcessImpl();public void purchaseGoods(String goodName,String consigneeInformation) {purchaseProcess.pickGoods(goodName);purchaseProcess.addCart(goodName);purchaseProcess.addConsigneeInformation(consigneeInformation);purchaseProcess.pay();}
}
客户端:
public class Client{public static void main(String[] args) {Shopping shopping = new Shopping();shopping.purchaseGoods("华为Mate40 Pro","上海");}
}
运行结果如下:
如果需要添加支付方式呢,我们还需要重新设计购买的步骤,具体的代码实现如下:
定义一个支付方式实现类:
public class PayMode {public void payMode(String payMode){System.out.println("支付方式:"+payMode);}
}
改造购物方式方法中的代码,新增一个支付方式:
public class Shopping {private PurchaseProcessImpl purchaseProcess = new PurchaseProcessImpl();private PayMode mode = new PayMode();public void purchaseGoods(String goodName,String consigneeInformation,String payMode) {purchaseProcess.pickGoods(goodName);purchaseProcess.addCart(goodName);purchaseProcess.addConsigneeInformation(consigneeInformation);mode.payMode(payMode);purchaseProcess.pay();}
}
客户端:
public class Client{public static void main(String[] args) {Shopping shopping = new Shopping();shopping.purchaseGoods("华为Mate40 Pro","上海","支付宝");}
}
运行结果如下:
五、总结
优点:
1、减少系统相互依赖:外观模式使得客户端和子系统的复杂关系放在外观类中,外界仅需面对一个简单的外观类,大大降低了客户与子系统间的耦合关系。
2、提高灵活性:通过引入外观类,可以在不影响其他子系统的情况下修改子系统。
3、更好的层次结构:外观模式可以更好地定义系统不同层次的功能。
缺点:
1、不符合开闭原则。如果需要修改外观类,有可能需要修改所有客户端代码。
使用场景:
1、提供一个简单的接口以屏蔽子系统组件的复杂性。
2、在层次化结构中定义入口点。
符合的设计原则:
1、 依赖倒转原则(Dependence Inversion Principle)
外观类与子系统之间形成了一种逆向的依赖关系,外观类依赖于抽象接口,而子系统则实现这些抽象接口,这个依赖关系是倒置的,降低了外观类与子系统的耦合度。
2、 迪米特法则(Law of Demeter)
外观类与子系统之间遵循最小知识原则,外观类只与需要交互的子系统直接通信,而不关心子系统内部的实现细节,降低了耦合度。
简单来说,外观模式通过提供一个高层接口来封装细节,简化子系统使用,使子系统之间解耦,它提高了程序的灵活性和可维护性。