目录
一、基础概念
二、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 {
@Override
public void pickGoods(String goodName) {
System.out.println("挑选的商品:"+goodName);
}
@Override
public void addCart(String goodName) {
System.out.println("将《"+goodName+"》添加到购物车!");
}
@Override
public void addConsigneeInformation(String consigneeInformation) {
System.out.println("您填写的收货地址:"+consigneeInformation);
}
@Override
public 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)
外观类与子系统之间遵循最小知识原则,外观类只与需要交互的子系统直接通信,而不关心子系统内部的实现细节,降低了耦合度。
简单来说,外观模式通过提供一个高层接口来封装细节,简化子系统使用,使子系统之间解耦,它提高了程序的灵活性和可维护性。