外观模式案例引入
要求,组建一个家庭影院,DVD播放器,投影仪,自动屏幕,环绕立体声,爆米花机,实现家庭影院的功能。过程为,直接用遥控器,统筹各设备开关,开爆米花机,放下屏幕,开投影仪,开音响,开dvd,选dvd,取爆米花,调暗灯光,播放电影,观影结束后,关闭各设备。
传统方式实现案例
无具体代码
传统方式实现案例分析
- 1.在ClientTest的main方法中,创建各个子系统的对象,并直接去调用子系统(对象)的相关方法,会导致调用过程混乱,没有清晰的过程。
- 2.不利于在ClientTest中,去维护对子系统的操作。
- 3.解决思路,定义一个高层接口,给子系统的一组方法,提供一个一致的界面(比如在高层接口,提供四个方法,ready,play,pause,end),用来访问子系统的一群接口。
- 4.通过定义一个一致的接口(界面类),用以屏蔽内部子系统的细节,使得调用端只需和接口产生调用,无需关心子系统的内部细节。=> 外观模式。
基本介绍
- 1.外观模式(facade pattern),也叫”过程模式”,外观模式为子系统的一组接口提供了一个一致的界面,此模式定义了一个高层接口,这个接口使得子系统更易使用。
- 2.外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心子系统的内部细节。
外观模式原理类图
类图说明
- 1.外观类,为调用者,提供统一的接口,外观类知道那些子系统负责处理请求,从而将调用者的请求代理给适当子系统的对象。、
- 2.调用者,外观接口的使用者。
- 3.子系统的集合,指模块或者子系统,处理Facede对象指派的任务,是功能的实际提供者。
外观模式实现案例代码
/** * @author 长名06 * @version 1.0 * 界面类 */public class HomeTheaterFacade { private DVDPlayer dvdPlayer = DVDPlayer.getDvdPlayer(); public Popcorn popcorn = Popcorn.getPopcorn(); public Projector projector = Projector.getProjector(); public Stereo stereo = Stereo.getStereo(); public Screen screen = Screen.getScreen(); public TheaterLight theaterLight = TheaterLight.getTheaterLight(); public void ready(){ popcorn.on(); popcorn.pop(); dvdPlayer.on(); projector.on(); screen.down(); stereo.on(); theaterLight.dim(); } public void play(){ dvdPlayer.play(); } public void end(){ popcorn.off(); dvdPlayer.off(); projector.off(); screen.up(); stereo.off(); theaterLight.off(); } public void pause(){ dvdPlayer.pause(); stereo.setVolume(); }}/** * @author 长名06 * @version 1.0 * 爆米花机 */public class Popcorn { private static Popcorn popcorn = new Popcorn(); public static Popcorn getPopcorn(){ return popcorn; } private Popcorn(){ } public void on(){ System.out.println("爆米花机 打开"); } public void off(){ System.out.println("爆米花机 关闭"); } public void pop(){ System.out.println("爆米花机 爆米花中"); }}/** * @author 长名06 * @version 1.0 * 投影仪 */public class Projector { private static Projector projector = new Projector(); public static Projector getProjector(){ return projector; } private Projector() { } public void on(){ System.out.println("投影仪 打开"); } public void off(){ System.out.println("投影仪 关闭"); } public void focus(){ System.out.println("投影仪 聚焦"); }}/** * @author 长名06 * @version 1.0 * 投影屏幕 */public class Screen { private static Screen screen = new Screen(); public static Screen getScreen(){ return screen; } private Screen() { } public void down(){ System.out.println("放下 投影屏幕"); } public void up(){ System.out.println("升起 投影屏幕"); }}/** * @author 长名06 * @version 1.0 * 立体声 */public class Stereo { private static Stereo stereo = new Stereo(); public static Stereo getStereo() { return stereo; } private Stereo() { } public void on() { System.out.println("立体声 打开"); } public void off() { System.out.println("立体声 关闭"); } public void setVolume(){ System.out.println("立体声 设置音量"); }}/** * @author 长名06 * @version 1.0 * 灯光 */public class TheaterLight { private static TheaterLight theaterLight = new TheaterLight(); public static TheaterLight getTheaterLight(){ return theaterLight; } private TheaterLight() { } public void on(){ System.out.println("打开灯光"); } public void off(){ System.out.println("关闭灯光"); } public void dim(){ on();//先打开再调暗 System.out.println("调暗灯光"); } public void bright(){ System.out.println("调量灯光"); }}/** * @author 长名06 * @version 1.0 * dvd播放器 */public class DVDPlayer { private static DVDPlayer dvdPlayer = new DVDPlayer(); public static DVDPlayer getDvdPlayer(){ return dvdPlayer; } private DVDPlayer(){ } public void on(){ System.out.println(" dvd播放器 打开"); } public void off(){ System.out.println(" dvd播放器 关闭"); } public void pause(){ System.out.println(" dvd播放器 暂停"); } public void play(){ System.out.println(" dvd播放器 播放"); }}//调用者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(); }}
外观模式在Mybatis框架的源码分析
//org.apache.ibatis.session.Configuration类的方法 public MetaObject newMetaObject(Object object) { return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory); }//MetaObject的forObject方法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); } } //会调用到MetaObject类中的该方法 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); } }
外观模式的注意事项和细节
- 1.外观模式对外屏蔽了子系统的细节,因此外观模式降低了客户端对子系统使用的复杂性。
- 2.外观模式对客户端和子系统的耦合关系-解耦,让子系统内部的模块更易于维护和扩展。
- 3.通过合理的使用外观模式,可以帮我们更好的划分访问的层次。
- 4.当系统需要进行分层设计时,可以考虑外观模式。
- 5.在维护一个遗留的大型系统时,可能这个系统已经变得非常难以维护和扩展,此时可以考虑为新系统开发一个Facade类,来提供遗留系统的比较清晰简单的接口,让新系统和Facade类交互,提高复用性。
- 6.不能过多的或者不合理的使用外观模式,要以让系统有层次,利于维护为目的,考虑是使用外观模式好,还是直接调用模块好。
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。