外观模式介绍
该模式定义了一个高层接口,为子系统中的多个模块协同完成某种功能需求提供了一个简单的对外的接口,用户可以通过使用该接口来完成该功能。是一种结构型模式,可以隐藏系统的复杂性。
外观模式参与角色
参与角色 | 功能 |
---|---|
外观角色 | 对外提供一个完成某种功能的接口,在内部持有相关子功能角色 |
子系统角色 | 实现了系统的功能,在外观角色中被使用 |
客户角色 | 调用了对外提供的接口(外观角色),以此来实现相关功能 |
外观模式UML
相关案例
小明想组装一个台式机,在购买内存条、硬盘、主板、cup等之后,但他不会组装,如果要自己组装的话,他需要去收集相关资料,但是现在他的一个表哥会组装电脑,所以他决定请他表哥帮忙。下面我们将使用这个案例来实现外观模式。
案例分析
分析上面的案例小明获得一台组装的台式机有两种方式。
第一种:自己去网上找相关资料,然后自己动手组装(不使用外观模式,在客户角色中直接调用子系统角色)
第二种:让自己的表哥帮自己装(使用外观模式,表哥就相当于一个外观角色,而小明只需要请表哥帮个忙就行(在客户角色中使用外观角色来完成对应的功能))。
两种方法的比较:首先我们需要明确小明的需求是获得一个台式机,那么学习如何装机对小明的来说不是必须的,他没有必要去学习如何组装机器,所以我们在这种情况下我们让小明去学习如何组装台式机是不恰当的(就好比去餐馆吃饭一样我的需求是吃饭而不是去餐馆自己炒菜然后在吃)。而如果采用第二种方面我们既能很好的满足小明这个客户的需求,而且他又不需要去了解过多的内容。(实现了类与类之间的解耦)。
在确定选用第二种方法后三种角色如下:
外观角色:表哥,内部持有完成相关功能的子系统角色。
子系统角色:实现了子系统的功能,在这里就是组装Cup,组装硬盘等。
客户角色:在内部调用了外观角色来完成某种功能,就是小明请求表哥帮忙。
案例实现
外观角色代码:
package facade.pattern;
/**
* @Introduction 外观角色,表哥类,实现了组装台式机的功能
*
*/
public class Facade {
//持有完成相关功能的子系统角色
private YingPan yingpan;
private NeiCun neicun;
private Cpu cpu;
private ZhuBan zhuban;
//在创建对象的时候进行实例化
public Facade() {
yingpan=new YingPan();
neicun=new NeiCun();
cpu=new Cpu();
zhuban=new ZhuBan();
}
//使用这些子系统角色完成某种功能
public void assembleComputer() {
System.out.println("表哥组装电脑");
yingpan.assembleYingPan();
neicun.assembleNeiCun();
cpu.assembleCpu();
zhuban.assembleZhuBan();
System.out.println("组装完毕");
}
}
子系统角色代码:
(1)组装cup代码
package facade.pattern;
/**
* @Introduction 子系统角色,Cpu类,实现了组装Cpu的方法
*/
public class Cpu {
public void assembleCpu() {
System.out.println("组装Cpu");
}
}
(2)组装硬盘代码
package facade.pattern;
/**
* @Introduction 子系统角色,硬盘类,实现了组装硬盘的方法
*/
public class YingPan {
public void assembleYingPan() {
System.out.println("组装硬盘");
}
}
(3)组装内存代码
package facade.pattern;
/**
* @Introduction 子系统角色,内存类,实现了组装内存的方法
*/
public class NeiCun {
public void assembleNeiCun() {
System.out.println("组装内存");
}
}
(4)组装主板代码
package facade.pattern;
/**
* @Introduction 子系统角色,主板类,实现了组装主板的方法
*/
public class ZhuBan {
public void assembleZhuBan() {
System.out.println("组装主板");
}
}
客户角色代码:
package facade.pattern;
/**
* @Introduction 客户角色类,模拟了在小明请求表哥帮他组装电脑的功能(使用外观角色完成某个特定的功能)
*/
public class Customer {
public static void main(String[] args) {
Facade biaoGe=new Facade();//创建一个外观角色对象
System.out.println("小明请求表哥组装电脑");
biaoGe.assembleComputer();
}
}
外观模式的优缺点
优点:
- 降低了类与类之间的耦合度。通过在两个模块之间增加一个中间接口,减少了两个模块的耦合度,使得代码的可扩展性和可维护性得到了提升。
- 对客户端屏蔽了子系统的使用过程,使得子系统使用更为方便。
缺点:
如果设计不当,增加新的子系统时我们需要更改外观角色中的代码,这不符合开放—封闭原则。
使用场景
- 在设计一个软件的最初阶段我们应该考虑建立层与层之间的外观模式。
- 对于一个功能复杂的系统我们可以使用外观模式来完成使用该系统的简单化。