设计模式--外观模式

案例

组建一个家庭影院:
DVD播放器,投影仪,自动屏幕,环绕立体声,爆米花机,灯光,要求完成使用家庭影院的功能,其过程为:

  • 直接用遥控器统筹各设备开关
  • 开爆米花机
  • 放下屏幕
  • 开投影仪
  • 开音响
  • 开DVD,选dvd
  • 去拿爆米花
  • 调暗灯光
  • 播放
  • 观影结束后,关闭各种设备
传统解决方案

传统解决方案
客户端直接创建并调用各子系统的相关功能方法

传统解决方案带来的问题

在客户端直接调用子系统的方法,会造成调用过程混乱,没有清晰的过程,同时客户端过多的关注子系统的内部实现,使得客户端调用子系统的难度升高,不利于维护对子系统的操作

使用外观模式解决问题

使用外观模式解决问题
HomeTheaterFacade:外观类,定义了客户端和各子系统之间的一个高层调用接口界面,给子系统中的一组接口提供一个一致的界面(ready,end,play,pause),用来统一调度子系统中的一群接口,以屏蔽内部子系统的细节,使得客户端只需跟这个接口发送调用。而无需关心这个子系统的内部细节

/**
 * 
 * @ClassName FacadePattern
 * @Description 外观模式
 * @author fuling
 * @date 2020年11月15日 上午10:57:09
 */
public class FacadePattern {
	public static void main(String[] args) {
		//创建一个家庭影院遥控器外观类
		HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade();
		System.out.println("观影前准备");
		homeTheaterFacade.ready();
		System.out.println("=============================");
		System.out.println("开始观影");
		homeTheaterFacade.play();
		System.out.println("=============================");
		System.out.println("暂停观影");
		homeTheaterFacade.pause();
		System.out.println("=============================");
		System.out.println("结束观影");
		homeTheaterFacade.end();
	}
}

/**
 * 
 * @ClassName HomeTheaterFacade
 * @Description 外观类(家庭影院遥控器)
 * @author fuling
 * @date 2020年11月15日 上午10:57:57
 */
class HomeTheaterFacade{
	
	//组合了家庭影院的各种设备
	DVDPlayer dvdPlayer = new DVDPlayer();
	Projector projector = new Projector();
	Stereo stereo = new Stereo();
	Popcorn popcorn = new Popcorn();
	Screen screen = new Screen();
	Light light = new Light();
	
	
	//观影前的准备工作
    void ready() {
    	//开爆米花机
    	popcorn.on();
    	//放下屏幕
    	screen.down();
    	//开投影仪
    	projector.on();
    	//开音响
    	stereo.on();
    	//开DVD,选dvd
    	dvdPlayer.on();
    	dvdPlayer.setDVD();
    	//去拿爆米花
    	popcorn.pop();
    	//调暗灯光
    	light.dim();
    }
    
    //观影结束的后的处理
    void end() {
    	//调亮灯光
    	light.bright();
    	//关掉DVD
    	dvdPlayer.off();
    	//关掉音响
    	stereo.off();
    	//关闭投影仪
    	projector.off();
    	//上升屏幕
    	screen.up();
    	//关闭爆米花机
    	popcorn.off();
    }
    
    //开始观影
    void play() {
    	dvdPlayer.play();
    }
    
    //暂停观影
    void pause() {
    	dvdPlayer.pause();
    }
}

/**
 * 
 * @ClassName DVDPlayer
 * @Description DVD播放器
 * @author fuling
 * @date 2020年11月15日 上午11:03:18
 */
class DVDPlayer{
	//打开DVD播放器
	void on() {
		System.out.println("打开DVD播放器");
	}
	
	//关闭DVD播放器
	void off() {
		System.out.println("关闭DVD播放器");
	}
	
	//开始播放
	void play() {
		System.out.println("开始播放");
	}
	
	
	//暂停播放
	void pause() {
		System.out.println("暂停播放");
	}
	
	
	//选择dvd
	void setDVD() {
		System.out.println("选择dvd");
	}
}

/**
 * 
 * @ClassName Projector
 * @Description 投影仪
 * @author fuling
 * @date 2020年11月15日 上午11:07:02
 */
class Projector{
	
	//打开投影仪
	void on() {
		System.out.println("打开投影仪");
	}
	
	//关闭投影仪
	void off() {
		System.out.println("关闭投影仪");
	}
	
	//聚焦投影仪
	void focus() {
		System.out.println("聚焦投影仪");
	}
	
	//移动投影仪位置
	void zoom() {
		System.out.println("移动投影仪位置");
	}
}


/**
 * 
 * @ClassName Stereo
 * @Description 环绕立体声系统
 * @author fuling
 * @date 2020年11月15日 上午11:09:02
 */
class Stereo{
	
	//打开环绕立体声
	void on() {
		System.out.println("打开环绕立体声");
	}
	
	//关闭环绕立体声
	void off() {
		System.out.println("关闭环绕立体声");
	}
	
	//调节声音
	void setVolume(int volume) {
		System.out.println("调节声音到" + volume);
	}
}

/**
 * 
 * @ClassName Popcorn
 * @Description 爆米花机
 * @author fuling
 * @date 2020年11月15日 上午11:11:15
 */
class Popcorn{
	
	//打开爆米花机
	void on() {
		System.out.println("打开爆米花机");
	}
	
	//关闭爆米花机
	void off() {
		System.out.println("关闭爆米花机");
	}
	
	//做爆米花
	void pop(){
		System.out.println("拿爆米花");
	}
}


/**
 * 
 * @ClassName Screen
 * @Description 自动屏幕
 * @author fuling
 * @date 2020年11月15日 上午11:18:12
 */
class Screen{
	//上升屏幕
	void up() {
		System.out.println("上升屏幕");
	}
	
	//放下屏幕
	void down() {
		System.out.println("放下屏幕");
	}
}


/**
 * 
 * @ClassName Light
 * @Description 影院灯光
 * @author fuling
 * @date 2020年11月15日 上午11:20:19
 */
class Light{
	
	//开灯
	void on() {
		System.out.println("开灯");
	}
	
	//关灯
	void off() {
		System.out.println("关灯");
	}
	
	
	//调暗灯光
	void dim() {
		System.out.println("调暗灯光");
	}
	
	
	//调亮灯光
	void bright() {
		System.out.println("调亮灯光");
	}
}
外观模式小结

外观模式模板
外观类(Facade):为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象
调用者(Client):外观接口的调用者
子系统的集合:指模块或者子系统,处理外观对象指派的任务,它是功能的实际提供者

  • 外观模式可以理解为转换一群接口,客户只要调用一个接口,而不用调用多个接口才能达到目的。比如在pc上安装软件时经常有一键安装选项
  • 外观模式就是解决多个复杂接口带来的使用困难,起到简化用户操作的作用
  • 外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端使用子系统的复杂性
  • 外观模式降低了客户端与子系统的耦合关系,让子系统内部的模块更易维护和扩展
  • 合理的使用外观模式,可以帮我们更好的划分访问层次,当系统需要进行分层设计时,可以考虑使用该模式
  • 在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为这些遗留的系统开发一个外观类,封装对这些遗留系统的调用细节,为新系统提供一个统一调用的接口(让新系统直接与外观类交互),提高复用性
  • 不能过多的或者不合理的使用外观模式,使用外观模式还是直接调用模块,要以让系统有层次,利于维护为目的,如果系统很简单,那么就可以直接调用模块
外观模式在mybatis框架中的应用
//外观类
public class Configuration {
	//组合了三个工厂模块
	protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    protected ObjectFactory objectFactory = new DefaultObjectFactory();
    protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();

	//对外的统一接口,将三种工厂模块传到MetaObject.forObject中,由MetaObject.forObject决定如何调用三种工厂模块的方法
	public MetaObject newMetaObject(Object object) {
    	return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
  	}
}
public class MetaObject {
	public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    	if (object == null) {
      		return SystemMetaObject.NULL_META_OBJECT;
    	} else {
      		return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
    	}
  	}
  	
  	private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    	this.originalObject = object;
    	this.objectFactory = objectFactory;
    	this.objectWrapperFactory = objectWrapperFactory;
    	this.reflectorFactory = reflectorFactory;

    	if (object instanceof ObjectWrapper) {
      		this.objectWrapper = (ObjectWrapper) object;
    	} else if (objectWrapperFactory.hasWrapperFor(object)) {
      		this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    	} else if (object instanceof Map) {
      		this.objectWrapper = new MapWrapper(this, (Map) object);
    	} else if (object instanceof Collection) {
      		this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    	} else {
      		this.objectWrapper = new BeanWrapper(this, object);
    	}
  	}
}

源码类图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值