设计模式学习(七) 外观模式

引入


定义:外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

UML类图

 

这个模式类图我么可以感受到,外观的意图是提供一个简单的接口,好让一个子系统更容易使用。

1.Facade 角色 对外提供统一的接口,让客户端访问子系统

2.子系统是一个集合或者多个系统,每个子系统都可以被客户端直接调用,或者通过facade调用。

示例

引用head first 的一个例子

我们这里有一套家庭影院系统。我们看看这些组件的组成

我们在看电影之前要做的事情

1.打开爆米花机

2.开始爆米花

3.将灯光调暗

4.放下屏幕

5.打开投影仪

。。。。

打开dvd播放器

开始播放dvd

只想观看一部影片,却做了这么多繁琐的操作。。。。

而且每次看完电影还要把所有都关掉,这简直太不友好了。我们决定使用外观模式解决这个糟糕的问题!

改造

我们需要一个外观,通过外观模式,实现一个提供更合理的接口的外观类,你可以将一个复杂的子系统变得更容易使用。如果你需要复杂子系统的强大威力,还是可以使用原来的复杂接口。但如果你需要的是一个方便使用的接口,那就是使用外观。

现在,我们只需药调用家庭影院外观所提供的方法,不必再调用这个子系统的方法。所以,现在我们看电影,只需药调用watchMovie()就可以了,灯光,dvd播放器,投影仪,公放等,一切全部搞定

外观只是提供你更直接的操作,并未将原来的子系统阻隔起来。如果你需要子系统类的更高层功能,还是可以使用原来的子系统。

外国模式和适配器模式对比:

1.外观不只是简化了接口,也是将客户从组件的子系统中解耦

2.外观和适配器可以包装许多类,但外观的意图是简化接口,而适配器的意图是将接口转化成不同的接口。

示例

这里引用head first上的一个家庭影院的例子(可能不是很恰当,重在说明思想),基于上面模型的例子

 

子系统类

package com.zpkj.project15;
/**
 * 公放类
 */
public class Amplifier {
	
	private Tuner tuner;
	
	private CdPlayer cdPlayer;
	
	private DvdPlayer dvdPlayer;

	public Amplifier(Tuner tuner, CdPlayer cdPlayer, DvdPlayer dvdPlayer) {
		super();
		this.tuner = tuner;
		this.cdPlayer = cdPlayer;
		this.dvdPlayer = dvdPlayer;
	}
	
	public void onDvd(){
		System.out.println("开启公放");
		
	}
	public void offDvd(){
		System.out.println("关闭公放");
	}
	
	public void setSurroundSound(){
		dvdPlayer.setSurroundAudio();
	}
	public void dvdPlay(){
		dvdPlayer.play();
	}

}
package com.zpkj.project15;
/**
 * cd播放器
 */
public class CdPlayer {
	

	public void on(){
		System.out.println("开启cd");
	}
	public void off(){
		System.out.println("关闭cd");
	}
	public void stop(){
		System.out.println("暂停");
	}
	public void play(){
		System.out.println("开始播放");
	}

}
package com.zpkj.project15;
/**
 * dvd播放器
 */
public class DvdPlayer {

	public void on(){
		System.out.println("开启dvd");
	}
	public void off(){
		System.out.println("关闭dvd");
	}
	public void stop(){
		System.out.println("暂停");
	}
	public void play(){
		System.out.println("开始播放");
	}

	public void setSurroundAudio(){
		System.out.println("环绕音");
	}

}
package com.zpkj.project15;
/**
 * 爆玉米花设配
 */
public class PopcornPopper {

	
	public void on(){
		System.out.println("开启爆米花机");
	}
	public void off(){
		System.out.println("关闭爆米花机");
	}
	public void pop(){
		System.out.println("爆爆米花");
	}
}
package com.zpkj.project15;
/**
 * 投影仪设配
 */
public class Projector {
	
	private DvdPlayer dvdPlayer;

	public Projector(DvdPlayer dvdPlayer) {
		super();
		this.dvdPlayer = dvdPlayer;
	}
	
	public void on(){
		System.out.println("开启投影");
	}
	public void off(){
		System.out.println("关闭投影");
	}
	
	public void tvMode(){
		System.out.println("观影模式");
	}
	
	public void wideScreenMode(){
		System.out.println("宽屏模式");
	}
}
package com.zpkj.project15;
/**
 * 屏幕
 */
public class Screen {
	
	public void up(){
		System.out.println("屏幕上升");
	}
	
	public void down(){
		System.out.println("屏幕下降");
	}

}
package com.zpkj.project15;
/**
 * 影院灯光
 */
public class TheaterLight {
	
	public void on(){
		System.out.println("开启影院灯光");
	}

	public void off(){
		System.out.println("关闭影院灯光");
	}
	public void dim(){
		System.out.println("观影模式灯光");
	}
}
package com.zpkj.project15;
/**
 * 调音设配
 */
public class Tuner {


	public void on(){
		System.out.println("开启调音");
	}
	public void off(){
		System.out.println("关闭调音");
	}
	public void setAm(){
		System.out.println("加大声音");
	} 
	public void setPm(){
		System.out.println("减小声音");
	}
	


}

 

Facade 角色

package com.zpkj.project15;

public class HomeTheaterFacade {
	
	private Amplifier amplifier;
	
	private Tuner tuner;
	
	private DvdPlayer dvdPlayer;
	
	private CdPlayer cdPlayer;
	
	private Projector projector;
	
	private TheaterLight light;
	
	private Screen screen;
	
	private PopcornPopper popcornPopper;

	public HomeTheaterFacade(Amplifier amplifier, Tuner tuner,
			DvdPlayer dvdPlayer, CdPlayer cdPlayer, Projector projector,
			TheaterLight light, Screen screen, PopcornPopper popcornPopper) {
		super();
		this.amplifier = amplifier;
		this.tuner = tuner;
		this.dvdPlayer = dvdPlayer;
		this.cdPlayer = cdPlayer;
		this.projector = projector;
		this.light = light;
		this.screen = screen;
		this.popcornPopper = popcornPopper;
	}
	
	
	
	public void watchMovie(){
		System.out.println("let’s go");
		popcornPopper.on();
		popcornPopper.pop();
		light.on();
		light.dim();
		screen.down();
		projector.on();
		projector.wideScreenMode();
		amplifier.onDvd();
		amplifier.setSurroundSound();
		dvdPlayer.on();
		dvdPlayer.play();
		
	}
	
	public void endMovie(){
		System.out.println("shutting movie theater dowm...");
		popcornPopper.off();
		light.off();
		screen.up();
		projector.off();
		amplifier.offDvd();
		dvdPlayer.stop();
		dvdPlayer.off();
	}

}

Client角色

package com.zpkj.project15;


public class Client {
	
	public static void main(String[] args) {
		Tuner tuner = new Tuner();
		CdPlayer cdPlayer = new CdPlayer();
		DvdPlayer dvdPlayer = new DvdPlayer();
		Amplifier amplifier = new  Amplifier(tuner, cdPlayer, dvdPlayer);
		Projector projector = new Projector(dvdPlayer);
		TheaterLight theaterLight = new TheaterLight();
		Screen screen = new Screen();
		PopcornPopper popcornPopper = new PopcornPopper();
		HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(amplifier, tuner, dvdPlayer, cdPlayer, projector, theaterLight, screen, popcornPopper);
		homeTheaterFacade.watchMovie();
		System.out.println("-----------------");
		homeTheaterFacade.endMovie();
	}

}

结果

oo原则

1.最少知识原则:只和你的密友谈话

这个原则希望我们在设计中,不要让太多类耦合在一起,免得修改系统中一部分,会影响到其他部分。如果许多类之间相互依赖,那么这个系统就会变成一个易碎的系统,造成维护成本增加。

总结

1.当需要简化并统一一个很大的接口或者一群复杂的接口时,使用外观模式

2.外观将客户从一个复杂的子系统中解耦

3.实现一个外观,需要将子系统 组合进外观中,然后将工作委任给子系统执行。

4.你可以为一个子系统实现一个以上的外观。

源码下载

https://github.com/isheroleon/design

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值