开头说几句
博主的博客地址: https://www.jeffcc.top/
博主学习设计模式用的书是 Head First 的《设计模式》,强烈推荐配套使用!
什么是外观模式
权威定义:外观模式提供了一个统一的接口,用来访问子系统中的一群接口,外观模式定义了一个高层接口,让子系统更容易被使用。
博主的理解:外观模式的目的是为了简化系统中的复杂的接口的调用,比如我们要回家,那么每次都需要自己开锁、开灯、开风扇甚至打开电视等的操作,而这些操作要一步步自己实现的话就太累了,所以我们可以通过外观模式来设计一个一键回家启动设备的外观,我们只需要调用外观接口就能够做到这一系列复杂的操作了!
外观模式与适配器模式
外观模式:
- 目的是通过外观来调用一个大系统中的很多功能那个;使用的是组合,类的耦合度比较低。
- 一个系统中可以有许多的外观,增加了系统的可拓展性。
适配器模式:
- 目的是通过继承来把一个不需要的类伪装成需要的类,使用的是继承,耦合度相对而言比较高。
外观模式与命令模式
外观模式:通过组合的方法,组合的是一个大接口,接口中会有许多的实现;
命令模式:也是通过组合的方法,但是组合的是一个一个一个的具体的接口的实现方法;与命令模式的宏命令有点相似,但是组成不同;
设计原则
最少知识原则:简而言之就是只和你的“密友”谈话,在真实的设计中,则是需要避免出现很多类耦合在一起,以免造成以后修改系统的时候影响到其他部分的正常运行。我的理解就是在类中出现的对象越少越好,当然这是在能完成类的任务的前提下;
设计实例
设计一个家庭一键启动系统
项目类图
项目结构
风扇控制器
package fan;
/**
* 风扇上层接口
*/
public interface Fan {
void FanOnLow();
void FanOnHigh();
void FanOff();
}
package fan.impl;
import fan.Fan;
/**
* 风扇实现类
*/
public class FanImpl implements Fan {
@Override
public void FanOnLow() {
System.out.println("Fan is on Low!!!!");
}
@Override
public void FanOnHigh() {
System.out.println("Fan is on High!!!!");
}
@Override
public void FanOff() {
System.out.println("Fan is Off!!!!");
}
}
空调控制器
package airconditioner;
/**
* 空调上层接口
*/
public interface AirConditioner {
void AirConditionerOn();
void AirConditionerOff();
}
package airconditioner.impl;
import airconditioner.AirConditioner;
/**
* 空调实现类
*/
public class AirConditionerImpl implements AirConditioner {
@Override
public void AirConditionerOn() {
System.out.println("AirConditioner is on!!!!");
}
@Override
public void AirConditionerOff() {
System.out.println("AirConditioner is off!!!!");
}
}
灯光控制器
package light;
/**
* 灯光接口
*/
public interface Light {
// 规范定义开关灯功能
void lightOn();
void lightOff();
}
package light.impl;
import light.Light;
/**
* 灯光实现类
*/
public class LightImpl implements Light {
@Override
public void lightOn() {
System.out.println("All light is on!!!!");
}
@Override
public void lightOff() {
System.out.println("All light is off!!!!");
}
}
电视控制器
package tv;
/**
* TV上层接口
*/
public interface TV {
void tvOn();
void tvOff();
}
package tv.impl;
import tv.TV;
/**
* TV的具体实现类
*/
public class TvImpl implements TV {
@Override
public void tvOn() {
System.out.println("TV is on!!!!");
}
@Override
public void tvOff() {
System.out.println("TV is off!!!!");
}
}
回家一键启动外观
package facade;
import airconditioner.AirConditioner;
import fan.Fan;
import light.Light;
import tv.TV;
/**
* 回家一键启动的外观
*/
public class BackHomeFacade {
private Light light;
private TV tv;
private Fan fan;
private AirConditioner airConditioner;
/**
* 构造器 初始化
* @param light
* @param tv
* @param fan
* @param airConditioner
*/
public BackHomeFacade(Light light, TV tv, Fan fan, AirConditioner airConditioner) {
this.light = light;
this.tv = tv;
this.fan = fan;
this.airConditioner = airConditioner;
}
/**
* 实现外观模式的核心!
* 实现通过一个接口来调用子系统的一群接口!
*/
public void bcakHome(){
System.out.println("back home!!!!");
light.lightOn();
tv.tvOn();
airConditioner.AirConditionerOn();
fan.FanOnLow();
}
}
离家一键启动外观
package facade;
import airconditioner.AirConditioner;
import fan.Fan;
import light.Light;
import tv.TV;
/**
* 离家一键启动的外观
*/
public class LeaveHomeFacade {
private Light light;
private TV tv;
private Fan fan;
private AirConditioner airConditioner;
/**
* 构造器 初始化
* @param light
* @param tv
* @param fan
* @param airConditioner
*/
public LeaveHomeFacade(Light light, TV tv, Fan fan, AirConditioner airConditioner) {
this.light = light;
this.tv = tv;
this.fan = fan;
this.airConditioner = airConditioner;
}
/**
* 实现外观模式的核心!
* 实现通过一个接口来调用子系统的一群接口!
*/
public void leaveHome(){
System.out.println("leave home!!!");
light.lightOff();
tv.tvOff();
airConditioner.AirConditionerOff();
fan.FanOff();
}
}
测试
package test;
import airconditioner.AirConditioner;
import airconditioner.impl.AirConditionerImpl;
import facade.BackHomeFacade;
import facade.LeaveHomeFacade;
import fan.Fan;
import fan.impl.FanImpl;
import light.Light;
import light.impl.LightImpl;
import tv.TV;
import tv.impl.TvImpl;
/**
* 测试类
*/
public class FacadeTest {
public static void main(String[] args) {
// 初始化组件
AirConditioner airConditioner = new AirConditionerImpl();
Light light = new LightImpl();
Fan fan = new FanImpl();
TV tv = new TvImpl();
// 创建回家外观
BackHomeFacade backHomeFacade = new BackHomeFacade(light, tv, fan, airConditioner);
// 回家一键启动
backHomeFacade.bcakHome();
System.out.println("------------------------------------");
// 创建离家外观
LeaveHomeFacade leaveHomeFacade = new LeaveHomeFacade(light, tv, fan, airConditioner);
// 回家一键启动
leaveHomeFacade.leaveHome();
}
}
测试结果
back home!!!!
All light is on!!!!
TV is on!!!!
AirConditioner is on!!!!
Fan is on Low!!!!
------------------------------------
leave home!!!
All light is off!!!!
TV is off!!!!
AirConditioner is off!!!!
Fan is Off!!!!
回到定义
我们说的外观模式就是在诸多接口上定义再定义一个访问这些子接口的大接口,而在这个实例中就体现的淋漓尽致了,子接口群对应着这些单独的家具控制器,而大接口则是对应着我们的回家一键模式以及离家一键模式,这些就对应着我们的外观了,给子接口套上一层外观,方便了客户的调用。
同时这也是最少知识原则的体现,我们的外观与用户层只有一个接口的耦合,如果不使用外观模式的话,就会需要用户自己手动一个一个的调用我们的子接口,这样在用户层这一块就会导致直接与过多的类进行了耦合,违背了最少知识原则!
END
2019 年 9 月 21 日 09:48:36
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于