编程是一门艺术,大批量的改动显然是非常丑陋的做法,用心的琢磨写的代码让它变的更美观。
在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了。
软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。
外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
在日常编码工作中,我们都在有意无意的大量使用外观模式。只要是高层模块需要调度多个子系统(2个以上的类对象),我们都会自觉地创建一个新的类封装这些子系统,提供精简的接口,让高层模块可以更加容易地间接调用这些子系统的功能。尤其是现阶段各种第三方SDK、开源类库,很大概率都会使用外观模式。
外观(Facade)模式是“迪米特法则”的典型应用,它有以下主要优点:
外观(Facade)模式的不足:
外观(Facade)模式的结构比较简单,主要是定义了一个高层接口。它包含了对各个子系统的引用,客户端可以通过它访问各个子系统的功能。
外观(Facade)模式包含以下主要角色:
场景介绍:有加包装服务、采摘服务、发货服务,为了方便客户端使用,采用外观设计模式进行设计。
public class PackService { /** * 水果打包:防伪/加固/加急等 */ public void doPack(){ AbstractFactory factory = new AppleFactory(); /*得到包装*/ Bag bag = factory.getBag(); /*现需要增加防伪标识*/ /*防伪功能*/ bag = new CheckedBagDecorator(bag); /*加固功能*/ bag = new ReinforceBagDecorator(bag); /*加急功能*/ bag = new SpeedDecorator(bag); bag.pack(); } public void doSomeThine(){ System.out.println("doSomeThine"); } } public class PickService { /** * 采摘水果 */ public void doPick(){ //袋子型号 BagAbstraction pickBag = new SmallBag(); //袋子材质 Material material = new Paper(); pickBag.setMaterial(material); //开始采摘 pickBag.pick(); } public void doSomeThine(){ System.out.println("doSomeThine"); } } public class SendService { /** * 指定目的地,发送快递 */ public void doSend(){ //根目录 DistrictNode root = new DistrictNode("china"); //一线目录 root.addChild(new DistrictNode("shang hai")); root.addChild(new DistrictNode("tian jin")); DistrictNode districtNode = new DistrictNode("bei jing"); root.addChild(districtNode); //二级目录 districtNode.addChild(new DistrictNode("hai dian qu")); districtNode.addChild(new DistrictNode("xi cheng qu")); DistrictNode districtNode2 = new DistrictNode("chao yang qu"); districtNode.addChild(districtNode2); //三级目录 districtNode2.addChild(new LeafNode("san li tun ")); districtNode2.addChild(new LeafNode("guo mao")); System.out.println("请选定目的地:"+ JsonOutput.toJson(root)); /*以下物流运输业务*/ System.out.println("本次快递目的地:beijing-chanyangqu-sanlitun"); } public void doSomeThine(){ System.out.println("doSomeThine"); } } //外观类 public class OrderFacade { private PickService pickService; private PackService packService; private SendService sendService; public OrderFacade(){ pickService = new PickService(); packService = new PackService(); sendService = new SendService(); } /** * 客户订单处理类 */ public void doOrder(){ /*采摘*/ System.out.println("--------------"); pickService.doPick(); /*包装*/ System.out.println("--------------"); packService.doPack(); /*快递*/ System.out.println("--------------"); sendService.doSend(); } } public static void main(String[] args){ OrderFacade orderFacade = new OrderFacade(); orderFacade.doOrder(); }
通常在以下情况下可以考虑使用外观模式: