**
设计模式(九)之外观模式
**
-
案例说明
在一个悠闲的周末早晨,你一个人待在家里不想做饭,但不做又饿得慌,所以只能自己做饭、准备吃饭的程序、洗碗,想想都麻烦,我们先看看这样做的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、不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。 要以让系统有层次,利于维护为目的。