设计模式--外观模式(十二)
来源:互联网 发布:免费qq软件下载 编辑:程序博客网 时间:2024/05/22 05:28
外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
知识点的梳理:
- "最少知识"原则:只和你的密友谈话;
- 当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观;
- 外观将客户从一个复杂的子系统中解耦;
- 实现一个外观,需要将子系统组合进外观中,然后将工作委托给子系统执行;
- 可以为一个子系统实现多个外观;
- 先来对比外观模式,适配器模式与装饰者模式
- 开始介绍前的惯例,来个栗子
- 需求:建立自己的家庭影院:包含DVD播放器,摄影机,自动屏幕,环绕立体声,爆米花机等等;
- 观看一部电影,我们需要执行如下步骤:
- 将以上步骤写成类或者方法:
- 其它问题:
- 看完电影后难道还要反向把所有步骤来一遍?
- 如果要听CD也这么麻烦?
- 如果要升级硬件系统,还要重新学习操作步骤?
- 引入外观模式
- 通过外观模式,实现一个提供合理接口的外观类,可以将一个复杂的子系统变得容易使用。
- 为家庭影院创建一个外观类HomeTheaterFacade的新类,对外暴露出几个简单的方法,例如watchMovie():
- 这个外观类将家庭影院的诸多组件视为一个子系统,通过调用这个子系统,来实现watchMovie()方法
- 现在,你的客户代码可以调用此家庭影院外观所提供的方法,而不必再调用这个子系统的方法。所以,想要看电影只要调用方法watchMovie()方法即可。
- 外观只是提供更直接的操作,并未将原来的子系统阻隔起来。如果需要子系统类的更高层功能,还是可以使用原来的子系统;
- 一些问题
- 外观封装了子系统的类,如果需要低层功能的客户如何接触这些类?
- 外观只是提供了子系统的简化接口,并没有封装子系统。子系统的功能依然暴露在外;
- 外观是否可以增加新的功能,或者它只是将没一个请求转由子系统执行?
- 完全可以;
- 每个子系统只能有一个外观吗?
- 可以为一个系统创建许多个外观;
- 除了提供一个比较简单的接口,外观模式还有其它的优点吗?
- 外观模式也允许你将客户实现从任何子系统中解耦;
- 比如,你升级家庭影院,采用全新的接口。如果当初的代码是针对外观而不是针对子系统编写的,现在就不需要改变客户代码,只需要修改外观代码就可以了;
- 适配器模式和外观模式的差异在于:前者包装一个类,后者代表许多类?
- 不对。适配器将一个或多个类接口变成客户端所期望的一个接口;
- 一个外观也可以只针对一个拥有复杂接口的类提供简化的接口;
- 两者的差异不在于它们包装了几个类,而在于它们的意图;适配器的意图是,"改变"接口符合客户的期望;而外观的意图是,提供子系统的一个简化接口;
- 构造家庭影院
package hey.adapter;
public class HomeTheaterFacade {
//需要的子系统组件全部在这里
Amplifieramp;
Tunertuner;
DvdPlayerdvd;
CdPlayercd;
Projectorprojector;
TheaterLightslights;
Screenscreen;
PopcornPopperpopper;
//外观将子系统中每一个组件的引用都传入它的构造函数中。然后外观把它们赋值给相应的实例变量
public HomeTheaterFacade(Amplifieramp,
Tunertuner,
DvdPlayerdvd,
CdPlayercd,
Projectorprojector,
Screenscreen,
TheaterLightslights,
PopcornPopperpopper){
this.amp =amp;
this.tuner =tuner;
this.dvd =dvd;
this.cd =cd;
this.projector =projector;
this.screen =screen;
this.lights =lights;
this.popper =popper;
}
//该方法将每项任务依次处理。每项任务都是委托子系统中相应的组件处理的
public void watchMovie(Stringmovie){
System.out.println("Get ready to watch a movie。。。");
popper.on();
popper.pop();
lights.dim(10);
screen.down();
projector.on();
projector.wideScreenMode();
amp.on();
amp.setDvd(dvd);
amp.setSurroundSound();
amp.setVolume(5);
dvd.on();
dvd.play(movie);
}
//该方法负责关闭一切。每项任务也都是委托子系统中合适的组件处理的
public void endMovie(){
System.out.println("Shutting movie theater down。。。");
popper.off();
lights.off();
screen.up();
projector.off();
amp.off();
dvd.stop();
dvd.eject();
dvd.off();
}
}
- 一众其它类~~~其它~~~
public class TheaterLights {
public void dim(inti) {
System.out.println("Theater Ceiling Lights dimming to " + i + "%");
}
public void off() {
System.out.println("Theater Ceiling Lights on");
}
}
public class PopcornPopper {
public void on() {
System.out.println("Popcorn Poper on");
}
public void pop() {
System.out.println("Popcorn Popper popping popcorn!");
}
public void off() {
System.out.println("Popcorn Poper off");
}
}
public class Screen {
public void down() {
System.out.println("Theater Screen going down");
}
public void up() {
System.out.println("Theater Screen going up");
}
}
public class Projector {
public void wideScreenMode() {
System.out.println("Top-O-Line Projector in widescreen mode (16*9 aspect ratio)");
}
public void on() {
System.out.println("Top-O-Line Projector on");
}
public void off() {
System.out.println("Top-O-Line Projector off");
}
}
public class Amplifier {
public void on() {
System.out.println("Top-O-Line Amplifier on");
}
public void setDvd(DvdPlayerdvd) {
System.out.println("Top-O-Line Amplifier setting DVD player to Top-O-Line DVD Player");
}
public void setSurroundSound() {
System.out.println("Top-O-Line Amplifier surrond sound on (5 speakers,1 subwoofer)");
}
public void setVolume(inti) {
System.out.println("Top-O-Line Amplifier setting volume to " + i);
}
public void off() {
System.out.println("Top-O-Line Amplifier off");
}
}
public class DvdPlayer {
private Stringmovie;
public void on() {
System.out.println("Top-O-Line DVD Player on");
}
public void play(Stringmovie) {
this.movie =movie;
System.out.println("Top-O-Line DVD Player playing \"" + movie + "\"");
}
public void stop() {
System.out.println("Top-O-Line DVD Player stopped \"" + movie + "\"");
}
public void eject() {
System.out.println("Top-O-Line DVD Player eject");
}
public void off() {
System.out.println("Top-O-Line DVD Player off");
}
}
- 测试
public class HomeTheaterTestDrive {
public static void main(String[]args) {
//实例化组件。正常的情况下,某个外观会被指派给客户使用,而不需要由客户自行创建外观
Amplifieramp = new Amplifier();
Tunertuner = new Tuner();
DvdPlayerdvd = new DvdPlayer();
CdPlayercd = new CdPlayer();
Projectorprojector = new Projector();
TheaterLightslights = new TheaterLights();
Screenscreen = new Screen();
PopcornPopperpopper = new PopcornPopper();
//根据子系统所有的组件来实例化外观
HomeTheaterFacadehomeTheater = new HomeTheaterFacade(amp,tuner,dvd,cd,projector,screen,lights,popper);
//使用简化的接口,先开启电影,然后关闭电影
homeTheater.watchMovie("Raiders of the lost Ark");
homeTheater.endMovie();
}
}
- 结果:
- 定义外观模式
- 外观模式的意图是要提供一个简单的接口,好让一个子系统更易于使用;
- 类图:
- "最少知识"原则
- 该原则告诉我们,要减少对象之间的交互,只留下几个"密友";
- 设计一个系统,不管是任何对象,都要注意它所交互的类有哪些,并注意它和这些类是如何交互的;
- 该原则期望我们在设计中,不要让太多的类耦合在一起,以免在修改系统时,影响其它部分;
- 如何避免这种情况?该原则提出了如下方针:就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:
- 该对象本身;
- 被当作方法的参数而传递进来的对象;
- 此方法所创建或实例化的任何对象;
- 对以上三句话的总结就是:如果某对象是调用其它的方法的返回结果,不要调用该对象的方法!
- 对象的任何组件;(把"组件"想象成是被实例变量所引用的任何对象。换句话说,把该对象想成是"有一个"关系)
- 为什么该原则会如此苛刻?
- 如果调用从另一个调用中返回的对象的方法,相当于向另一个对象的子部分发请求(而增加我们直接认识的对象数目)。在这种情况下,原则要我们改为要求该对象为我们做出请求。这样的话,我们就不需要认识该对象的组件了,比如:
- 将方法限定在界限内
- 下面的汽车类,展示了调用的方法,同时遵守了最少知识原则:
public class Car {
Engineengine;//这是一个类的组件,我们可以调用它的方法
public Car(){}
public void start(Keykey){
Doorsdoors = new Doors();//创建一个新对象,需要调用它的方法
booleanauthorized = key.turns();//被当作参数传递进来的对象,其方法可以被调用
if(authorized){
engine.start();//可以调用对象组件的方法
updateDashboardDisplay();//可以调用同一个对象内的本地方法
doors.lock();//可以调用你所创建或实例化的对象的方法
}
}
private void updateDashboardDisplay() {
//更新显示
}
}
- 最少知识原则的缺点
- 采用这个原则会导致更多的"包装"类被制造出来,以处理和其他组件的沟通,这可能导致复杂度和开发时间的增加,并降低运行时的性能;
- 外观和最少知识原则
- 设计模式--外观模式(十二)
- 大话设计模式十二:外观模式(facade)
- (十二)外观模式
- 设计模式之十二 外观模式-股票基金
- 面向对象的设计模式(十二),外观模式
- Android设计模式(二十二)-外观模式
- 设计模式--外观模式
- 设计模式-外观模式
- 设计模式:外观模式
- 设计模式----外观模式
- 设计模式------外观模式
- 设计模式 外观模式
- 设计模式-【外观模式】
- 设计模式-----外观模式
- 设计模式 - 外观模式
- 设计模式 - 外观模式
- 设计模式- 外观模式
- 设计模式-外观模式
- pymysql
- wget 介绍
- 动态内存分配 数组
- hdu5694(规律+分治)BD String
- Linux网络编程之accept函数
- 设计模式--外观模式(十二)
- 插入排序和插入排序的改进
- 割接
- laravel -- Eloquent 模型关联
- ListView中存在EditText,弹出键盘后焦点丢失问题。
- Centos7.3_64位安装Apache2.4_mysql5.7_php5.4(阿里云LAMP php环境搭建图文教程)
- 最长递增子序列
- 焦点图,轮播图效果
- 重构原则(一)