0.参考资料
1.概述
- 为子系统中的一组接口提供一个一致(稳定)的界面, Facade模式定义了一个高层接口,这个接口使得这一子系 统更加容易使用(复用)。 —《设计模式》GoF
- 外观模式(Facade),也叫“门面模式:外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端 只需跟这个接口发生调用,而无需关心这个子系统的内部细节
1.1动机
- 组件的客户端和组件中各种复杂的子系统有了
过多的耦合,随着外部客户程序和各子系统的演化,这种过多的耦 合面临很多变化的挑战。
1.2结构
- 其中子系统中, 各个组件的依赖由组件自行解决- - 
1.3说明
1. 外观类(Facade): 为调用端提供统一的调用接口, 外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当
子系统对象
1. 调用者(Client): 外观接口的调用者1. 子系统的集合:指模块或者子系统,处理Facade 对象指派的任务,他是功能的实际提供者
2.要点总结
宏观架构
1. 从客户程序的角度来看,Facade模式简化了整个组件系统的接口
; 对于组件内部与外部客户程序来说,达到了一种”解耦”的效 果 — 内部子系统的任何变化不会影响到Facade接口的变化。
1. Facade设计模式更注重从架构的层次去看整个系统, 而不是单个
类的层次。Facade很多时候更是一种架构设计模式。
1. Facade设计模式并非一个集装箱,可以任意地放进任何多个对象。
Facade模式中组件的内部应该是“相互耦合关系比较大的一系列 组件”, 而不是一个随意的功能集合。
微观代码
1. 外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复
杂性
1. 外观模式对客户端与子系统的耦合关系,让子系统内部的模块更易维护和扩展1. 通过合理的使用外观模式,可以帮我们更好的划分访问的层次1. 当系统需要进行分层设计时,可以考虑使用Facade模式1. 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时
可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口, 让新系统与Facade类交互,提高复用性
1. 不能过多的或者不合理的使用外观模式,要以让系统有层次,利于维护为目的选择 外观模式/直接调用模块
3.案例
需求
- 组建一个家庭影院:- DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的- 功能,其过程为:- • 直接用遥控器:统筹各设备开关- • 开爆米花机- • 放下屏幕- • 开投影仪- • 开音响- • 开DVD,选dvd- • 去拿爆米花- • 调暗灯光- • 播放- • 观影结束后,关闭各种设备
分析
- - 在ClientTest 的main方法中,创建各个子系统的对象,并直接去调用子系统(对象) 相关方法,会造成调用过程混乱,没有清晰的过程-
不利于在ClientTest 中,去维护对子系统的操作
- **解决思路**:- 定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比
如在高层接口提供四个方法 ready, play, pause, end ),用来访问子系统中的 一群接口
- 即通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,
使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 => 外观 模式
4.使用模式
改进引入案例
- 外观模式可以理解为转换一群接口,客户只
要调用一个接口,而不用调用多个接口才能 达到目的。比如:在pc上安装软件的时候经 常有一键安装选项(省去选择安装目录、安 装的组件等等),还有就是手机的重启功能 (把关机和启动合为一个操作)。
-
外观模式就是解决多个复杂接口带来的使用 困难,起到简化用户操作的作用
- 分析:- 类图: 
新案例
- 模拟去网吧玩电脑和回家
方案
- 使用外观模式,分为 三部分 _(准备 _- _玩电脑 _- _收尾)_- 每个部分的具体操作则调用具体的子部件组合而成
类图
- - 可以看到和客户端Client直接耦合的只有外观类, 而其三大步中的具体实现则有各种组件(互相调用)完成. 组件之间的依赖由组件自身解决.
代码
- 门面类
/*** @description: 网吧(准备 - 玩电脑 - 收尾)的外观类* 本案例简单模拟组件之间的依赖: 归属于User的RMB和SFZ*/public class InternetFacade {User user;WBManager manager;Computer computer;{user = new User("小明");manager = WBManager.getInstance();computer = Computer.getInstance();}// 玩电脑的准备工作public void ready(){user.gotoWb();manager.showComputer();manager.register(user);computer.on();}// 玩电脑中public void play(){computer.play();}// 中途加钱public void addTime(){computer.stop();manager.addTime(user);}// 下机走人public void end(){computer.shutdown();manager.getOut(user);user.backHome();}}
- 组件类
@Getterpublic class User {String name;public User(String name){this. name = name;}private SFZ mySfz = new SFZ();private RMB myRmb = new RMB();public void showSfz(){mySfz.show(name);}public void payRMB(){myRmb.pay(name);}public void addRMB(){myRmb.add(name);}public void gotoWb(){System.out.println("从家到了网吧");}public void backHome(){System.out.println("回到了家");}}// 身份证public class SFZ {public void show(String name){System.out.println("\t" + name + " SFZ: 展示了身份证");}}// 钱public class RMB {// 各种行为, 案例中就不具体调用...public void pay(String name){System.out.println("\t" + name + " RMB: 付了钱");}public void add(String name){System.out.println("\t" + name + " RMB: 收了钱");}}// 网管public class WBManager {private static WBManager instance = new WBManager();public static WBManager getInstance() {return instance;}public void register(User user) {System.out.println("前台上号中...(依赖 SFZ类 和 RMB类");System.out.println("\t展示身份证中...");user.showSfz();System.out.println("\t付钱中...");user.payRMB();System.out.println("前台上号成功");}public void showComputer(){System.out.println("网管介绍网吧座位分区中");}public void addTime(User user) {System.out.println("前台加钱中...(依赖 SFZ类 和 RMB类");System.out.println("\t展示身份证中...");user.showSfz();System.out.println("\t付钱中...");user.payRMB();System.out.println("前台加钱成功");}public void getOut(User user) {System.out.println("下机中...(依赖 SFZ类 和 RMB类");System.out.println("\t展示身份证中...");user.showSfz();System.out.println("\t退钱中...");user.addRMB();}}// 上的机子public class Computer {private static Computer instance = new Computer();public static Computer getInstance() {return instance;}public void on (){System.out.println("电脑开机");}public void play(){System.out.println("电脑游戏中");}public void stop(){System.out.println("电脑挂起");}public void shutdown(){System.out.println("电脑关机");}}
- 测试
public class Client {public static void main(String[] args) {InternetFacade internetFacade = new InternetFacade();// 玩电脑的前摇internetFacade.ready();// 玩电脑中internetFacade.play();// 可能的插曲: 余额不足准备加钱if (true){internetFacade.addTime();}// 后摇internetFacade.end();}}
从家到了网吧网管介绍网吧座位分区中前台上号中...(依赖 SFZ类 和 RMB类展示身份证中...小明 SFZ: 展示了身份证付钱中...小明 RMB: 付了钱前台上号成功电脑开机电脑游戏中电脑挂起前台加钱中...(依赖 SFZ类 和 RMB类展示身份证中...小明 SFZ: 展示了身份证付钱中...小明 RMB: 付了钱前台加钱成功电脑关机下机中...(依赖 SFZ类 和 RMB类展示身份证中...小明 SFZ: 展示了身份证退钱中...小明 RMB: 收了钱回到了家
5.经典使用
5.1MyBatis中Configuration.newMetaObject(Object obj) : MetaObject
代码
- 
类图
- 
