下图是状态模式的UML图。
结构
Facade
这个外观类为子系统中Packages 1、2、3提供一个共同的对外接口
Clients
客户对象通过一个外观接口读写子系统中各接口的数据资源。
Packages
客户可以通过外观接口读取的内部库。
下面看下一个小例子吧,看DVD的故事:
先得有个电视:
- public class TV {
- public void turnOn(){
- System.out.println("打开电视");
- }
- public void turnOff(){
- System.out.println("关闭电视");
- }
- }
DVD:
- public class DVD {
- public void turnOn(){
- System.out.println("打开DVD");
- }
- public void putDVD(MovieDisc movie){
- System.out.println("放进碟片");
- System.out.println("现在开始播放:"+movie.getMovieName());
- }
- public void takeOut(MovieDisc movie){
- System.out.println("停止播放:"+movie.getMovieName());
- System.out.println("取出碟片");
- }
- public void turnOff(){
- System.out.println("关闭DVD");
- }
- }
影片:
- public class MovieDisc {
- private String movieName ;
- public MovieDisc(String movieName){
- this.movieName = movieName;
- System.out.println("这个电影名字叫做:"+movieName);
- }
- public String getMovieName(){
- return movieName;
- }
- }
我们想看电影的时候:
- //打开电视,dvd,放进影片,开始看电影
- tv.turnOn();
- dvd.turnOn();
- dvd.putDVD(movie);
- //看完了,接着看另外一部
- dvd.takeOut(movie);
- MovieDisc movie2 = new MovieDisc("黄金大劫案");
- dvd.putDVD(movie2);
- //看完了,关机睡觉
- dvd.takeOut(movie);
- dvd.turnOff();
- tv.turnOff();
客户调用非常复杂,什么事都得自己做。。。
使用外观模式:
- public class HomeTheater {
- DVD dvd = null;
- TV tv =null;
- MovieDisc movie = null;
- public HomeTheater(DVD dvd,TV tv,MovieDisc movie){
- this.dvd = dvd;
- this.movie = movie;
- this.tv =tv;
- }
- public void watchMovie() {
- tv.turnOn();
- dvd.turnOn();
- dvd.putDVD(movie);
- }
- public void endMovie(){
- dvd.takeOut(movie);
- dvd.turnOff();
- tv.turnOff();
- }
- public void chageMovie(MovieDisc movie2){
- dvd.takeOut(movie);
- dvd.putDVD(movie2);
- this.movie = movie2;
- }
- }
当想看电影的时候呢:
- HomeTheater homeTheater = new HomeTheater(dvd, tv, movie);
- homeTheater.watchMovie();
- homeTheater.chageMovie(movie2);
- homeTheater.endMovie();
只需要调用几个简单的接口就可以了。
看下完整的测试类:
- public class Tets {
- public static void main(String[] args){
- //生成电视,DVD,碟片
- TV tv = new TV();
- DVD dvd = new DVD();
- MovieDisc movie = new MovieDisc("桃姐");
- //打开电视,dvd,放进影片,开始看电影
- tv.turnOn();
- dvd.turnOn();
- dvd.putDVD(movie);
- //看完了,接着看另外一部
- dvd.takeOut(movie);
- MovieDisc movie2 = new MovieDisc("黄金大劫案");
- dvd.putDVD(movie2);
- //看完了,关机睡觉
- dvd.takeOut(movie);
- dvd.turnOff();
- tv.turnOff();
- System.out.println("--------使用家庭影院-------");
- HomeTheater homeTheater = new HomeTheater(dvd, tv, movie);
- homeTheater.watchMovie();
- homeTheater.chageMovie(movie2);
- homeTheater.endMovie();
- }
- }
结果:
这个电影名字叫做:桃姐
打开电视
打开DVD
放进碟片
现在开始播放:桃姐
停止播放:桃姐
取出碟片
关闭DVD
关闭电视
停止播放:桃姐
取出碟片
这个电影名字叫做:黄金大劫案
放进碟片
现在开始播放:黄金大劫案
--------使用家庭影院-------
打开电视
打开DVD
放进碟片
现在开始播放:桃姐
停止播放:桃姐
取出碟片
放进碟片
现在开始播放:黄金大劫案
停止播放:黄金大劫案
取出碟片
关闭DVD
关闭电视
客户端,只短短调用几行代码,就实现了功能,没那么繁琐。
注意和其他设计模式的区别
代理模式
1 代理模式中的原类和代理类继承同一父类;
2 原类对象与代理类对象接口相同,功能一致;
3 起到了隐藏原类的作用。
适配器模式
1 只有适配器继承目标接口;
2 将原有类接口转换为目标代码需求的接口。
外观模式
是多个类的集成、统一适配。
学习外观模式很好的资料:
http://www.cnblogs.com/hegezhou_hot/archive/2010/12/06/1897398.html