**
**
案例说明
在一个悠闲的周末早晨,你一个人待在家里不想做饭,但不做又饿得慌,所以只能自己做饭、准备吃饭的程序、洗碗,想想都麻烦,我们先看看这样做的UML类图:
不用外观模式的传统写法 用Client模拟要做饭、准备吃饭的程序、洗碗的自己,午饭我们要吃蛋糕和吃汉堡,那就得自己做蛋糕、做汉堡、准备吃蛋糕的程序、准备吃汉堡的程序、收拾蛋糕的餐具、收拾汉堡的餐具;晚饭我们要吃饼干和披萨,那就得自己做饼干、做披萨、准备吃饼干的程序、准备吃披萨的程序、收拾饼干的餐具、收拾披萨的餐具,很麻烦。所以我们就想到雇一个人来帮我们做午晚饭和收拾餐具,自己只管吃就行了。
外观模式 FoodFacade就是我们雇佣来做饭洗碗的人,我们只需要告诉他,做午饭、准备吃午饭的程序、洗碗、做晚饭、准备吃晚饭的程序、洗碗,这样的指令就行了,我们不关心具体做饭、准备吃饭程序、洗碗的过程,这种模式就叫做外观模式。
食物的实体类
@Data public class Cake { private Cake(){} private final static Cake INSTANCE = new Cake(); public static Cake getInstance(){ return INSTANCE; } public void make(){ System.out.println("做蛋糕"); } public void eat(){ System.out.println("准备吃蛋糕的程序"); } public void clean(){ System.out.println("收拾吃蛋糕的餐具"); } } @Data public class Cookie { private Cookie(){} private final static Cookie INSTANCE = new Cookie(); public static Cookie getInstance(){ return INSTANCE; } public void make(){ System.out.println("做饼干"); } public void eat(){ System.out.println("准备吃饼干的程序"); } public void clean(){ System.out.println("收拾吃饼干的餐具"); } } @Data public class Hamburger { private Hamburger(){} private final static Hamburger INSTANCE = new Hamburger(); public static Hamburger getInstance(){ return INSTANCE; } public void make(){ System.out.println("做汉堡"); } public void eat(){ System.out.println("准备吃汉堡的程序"); } public void clean(){ System.out.println("收拾吃汉堡的餐具"); } } @Data public class Pizza { private Pizza(){} private final static Pizza INSTANCE = new Pizza(); public static Pizza getInstance(){ return INSTANCE; } public void make(){ System.out.println("做披萨"); } public void eat(){ System.out.println("准备吃披萨的程序"); } public void clean(){ System.out.println("收拾吃披萨的餐具"); } }被雇佣的人
public class FoodFacade { private Cake cake; private Cookie cookie; private Hamburger hamburger; private Pizza pizza; public FoodFacade(){ this.cake = Cake.getInstance(); this.cookie = Cookie.getInstance(); this.hamburger = Hamburger.getInstance(); this.pizza = Pizza.getInstance(); } public void lunchPrepare(){ cake.make(); hamburger.make(); } public void lunchEat(){ cake.eat(); hamburger.eat(); } public void lunchClean(){ cake.clean(); hamburger.clean(); } public void dinnerPrepare(){ cookie.make(); pizza.make(); } public void dinnerEat(){ cookie.eat(); pizza.eat(); } public void dinnerClean(){ cookie.clean(); pizza.clean(); } }客户端
public class Client { public static void main(String[] args) { FoodFacade foodFacade = null; // 如果有业务需求可以创建多个外观类,根据具体的业务需求来使用 foodFacade = new FoodFacade(); // 准备午饭 foodFacade.lunchPrepare(); // 吃午饭 foodFacade.lunchEat(); // 午饭收拾 foodFacade.lunchClean(); // 准备晚饭 foodFacade.dinnerPrepare(); // 吃晚饭 foodFacade.dinnerEat(); // 晚饭收拾 foodFacade.dinnerClean(); } }测试
D:\jdk8\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar=60715:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\bin" -Dfile.encoding=UTF-8 -classpath D:\jdk8\jre\lib\charsets.jar;D:\jdk8\jre\lib\deploy.jar;D:\jdk8\jre\lib\ext\access-bridge-64.jar;D:\jdk8\jre\lib\ext\cldrdata.jar;D:\jdk8\jre\lib\ext\dnsns.jar;D:\jdk8\jre\lib\ext\jaccess.jar;D:\jdk8\jre\lib\ext\jfxrt.jar;D:\jdk8\jre\lib\ext\localedata.jar;D:\jdk8\jre\lib\ext\nashorn.jar;D:\jdk8\jre\lib\ext\sunec.jar;D:\jdk8\jre\lib\ext\sunjce_provider.jar;D:\jdk8\jre\lib\ext\sunmscapi.jar;D:\jdk8\jre\lib\ext\sunpkcs11.jar;D:\jdk8\jre\lib\ext\zipfs.jar;D:\jdk8\jre\lib\javaws.jar;D:\jdk8\jre\lib\jce.jar;D:\jdk8\jre\lib\jfr.jar;D:\jdk8\jre\lib\jfxswt.jar;D:\jdk8\jre\lib\jsse.jar;D:\jdk8\jre\lib\management-agent.jar;D:\jdk8\jre\lib\plugin.jar;D:\jdk8\jre\lib\resources.jar;D:\jdk8\jre\lib\rt.jar;D:\ideaworkspace\design_pattern\design\target\classes;D:\dev_tools\repository\org\projectlombok\lombok\1.16.10\lombok-1.16.10.jar com.wd.facade.Client 做蛋糕 做汉堡 准备吃蛋糕的程序 准备吃汉堡的程序 收拾吃蛋糕的餐具 收拾吃汉堡的餐具 做饼干 做披萨 准备吃饼干的程序 准备吃披萨的程序 收拾吃饼干的餐具 收拾吃披萨的餐具 Process finished with exit code 0 总结 1、外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性; 2、外观模式对客户端与子系统的耦合关系,让子系统内部的模块更易维护和扩展; 3、通过合理的使用外观模式,可以帮我们更好的划分访问的层次; 4、当系统需要进行分层设计时,可以考虑使用Facade模式; 5、在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时 可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口, 让新系统与Facade类交互,提高复用性; 6、不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。 要以让系统有层次,利于维护为目的。