外观模式
影院管理项目
组建一个家庭影院:
DVD播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的
功能,其过程为:
• 直接用遥控器:统筹各设备开关
• 开爆米花机
• 放下屏幕
• 开投影仪
• 开音响
• 开DVD,选dvd
• 去拿爆米花
• 调暗灯光
• 播放
• 观影结束后,关闭各种设备
传统方式解决影院管理
传统方式解决影院管理问题分析
- 在ClientTest 的main方法中,创建各个子系统的对象,并直接去调用子系统(对象)
相关方法,会造成调用过程混乱,没有清晰的过程 - 不利于在ClientTest 中,去维护对子系统的操作
- 解决思路:定义一个高层接口,给子系统中的一组接口提供一个一致的界面(比
如在高层接口提供四个方法 ready, play, pause, end ),用来访问子系统中的
一群接口 - 也就是说 就是通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,
使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节 => 外观模式
举例介绍:
有些人可能炒过股票,但其实大部分人都不太懂,这种没有足够了解证券知识的情况下做股票是很容易亏钱的,刚开始炒股肯定都会想,如果有个懂行的帮帮手就好,其实基金就是个好帮手,支付宝里就有许多的基金,它将投资者分散的资金集中起来,交由专业的经理人进行管理,投资于股票、债券、外汇等领域,而基金投资的收益归持有者所有,管理机构收取一定比例的托管管理费用。
其实本篇要说的这个设计模式就和这很有关系,由于当投资者自己买股票时,由于众多投资者对众多股票的联系太多,反而不利于操作,这在软件中就成为耦合性太高,而有了基金后,就变成众多用户只和基金打交道,关心基金的上涨和下跌,而实际上的操作确是基金经理人与股票和其它投资产品打交道,这就是外观模式。
基本介绍
- 外观模式(Facade),也叫“过程模式:外观模式为子系统中的一组接口提供
一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加
容易使用 - 外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端
只需跟这个接口发生调用,而无需关心这个子系统的内部细节
外观模式的原理类图
1)外观类(Facade): 为调用端提供统一的调用接口, 外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象
2) 调用者(Client): 外观接口的调用者
3)子系统的集合:指模块或者子系统,处理Facade 对象指派的任务,他是功能的实际提供者
传统方式解决影院管理说明:
- 外观模式可以理解为转换一群接口,客户只
要调用一个接口,而不用调用多个接口才能
达到目的。比如:在pc上安装软件的时候经
常有一键安装选项(省去选择安装目录、安
装的组件等等),还有就是手机的重启功能
(把关机和启动合为一个操作)。 - 外观模式就是解决多个复杂接口带来的使用
困难,起到简化用户操作的作用、
外观模式应用实例
DVD播放器:
/**
* @author 孙一鸣 on 2020/2/11
*/
public class DVDPlaer {
//使用单例模式 (饿汉式)创建对象
private DVDPlaer() {
}
private static DVDPlaer dvdPlaer = new DVDPlaer();
public static DVDPlaer getDvdPlaer(){
return dvdPlaer;
}
public void on(){
System.out.println("dvd 打开中。。。");
}
public void off(){
System.out.println("dvd 关闭中。。。");
}
public void play(){
System.out.println("dvd 正在播放中。。。");
}
public void pause(){
System.out.println("dvd 暂停中。。。");
}
}
灯光控制:
package 设计模式.外观模式.GG;
/**
* 灯光
*
* @author 孙一鸣 on 2020/2/11
*/
public class TheaterLight {
//使用单例模式 (饿汉式)创建对象
private TheaterLight() {
}
private static TheaterLight theaterLight = new TheaterLight();
public static TheaterLight getTheaterLight(){
return theaterLight;
}
public void on(){
System.out.println("灯光 打开中。。。");
}
public void off(){
System.out.println("灯光 关闭中。。。");
}
public void dim(){
System.out.println("灯光调暗。。。");
}
public void bright(){
System.out.println("灯光调亮。。。");
}
}
外观类:
package 设计模式.外观模式.GG;
/**
* @author 孙一鸣 on 2020/2/11
*/
public class HomeTheaterFacade {
//定义各个子系统对象
private TheaterLight light;
private DVDPlaer dvdPlaer;
public HomeTheaterFacade() {
this.light = TheaterLight.getTheaterLight();
this.dvdPlaer = DVDPlaer.getDvdPlaer();
}
//使用影院分为四步
public void ready(){
light.on();//打开灯光
dvdPlaer.on();//打开DVD
}
public void play(){
dvdPlaer.play();//DVD播放中
}
public void pause(){
dvdPlaer.pause();//DVD暂停
}
public void end(){
light.off();
dvdPlaer.off();
}
}
测试:
/**
* @author 孙一鸣 on 2020/2/11
*/
public class Client {
public static void main(String[] args) {
HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
homeTheaterFacade.ready();
System.out.println("==============");
homeTheaterFacade.play();
System.out.println("==============");
homeTheaterFacade.pause();
System.out.println("==============");
homeTheaterFacade.end();
}
}
结果截图:
外观模式的注意事项和细节
- 外观模式对外屏蔽了子系统的细节因此外观模式降低了客户端对子系统使用的复
杂性 - 外观模式对客户端与子系统的耦合关系,让子系统内部的模块更易维护和扩展
- 通过合理的使用外观模式,可以帮我们更好的划分访问的层次
- 当系统需要进行分层设计时,可以考虑使用Facade模式
- 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统与Facade类交互,提高复用性
- 不能过多的或者不合理的使用外观模式,使用外观模式好,还是直接调用模块好。要以让系统有层次,利于维护为目的。