前言
在聊外观模式之前,我们先来聊聊体检过程。一般体检过程就是我们根据网上预定得日期空腹去体检中心。根据预定得项目,有一般检查、内科、外科、眼科、彩超、心电图、血常规、尿常规等等项目。
而我们往往第一次去是不知道这些房间是在哪里的,所以,我们一般会去求助现场得接待人员,通过它分别找到我们得体检目标具体位置,这一过程可以看做外观模式也称门面模式
专业定义
它是一种结构型设计模式,能为程序库、框架或其他复杂类提供一个简单的接口。又名门面模式,是一种通过为多个复杂得子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性
案例
现在,我们定义三个体验项目(内科、外科、眼科),和一个接待人员,一个测试类。
public class Receptionist {
private InternalMedicine inner;
private Ophthalmology eye;
private Surgical out;
public Receptionist() {
inner = new InternalMedicine();
eye = new Ophthalmology();
out = new Surgical();
}
public void say(String message) {
if ("我要体验".equals(message)) {
this.goHere();
}
}
public void goHere() {
System.out.println("欢迎来到我们体验中心!!!体验项目在那,去吧~");
inner.here();
eye.here();
out.here();
}
public static void main(String[] args) {
Receptionist receptionist = new Receptionist();
receptionist.say("我要体验");
}
}
// 内科
class InternalMedicine {
public void here() {
System.out.println("内科未见异常");
}
}
// 眼科
class Ophthalmology {
public void here() {
System.out.println("眼科注意保养");
}
}
// 外科
class Surgical {
public void here() {
System.out.println("外科未见异常");
}
}
输出结果:
模式分析
优缺点
优点
- 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类,你可以让自己的代码独立于复杂子系统;
缺点
- 不符合开闭原则,所有类都耦合在一起,修改很麻烦;
使用场景
- 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且,用户也可以越过外观类直接访问子系统;
- 引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性;
- 在层次化结构中,可以使用外观模式定义系统中每一层的入门,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度
需要注意的点
- 一个系统有多个外观类
在外观模式中,通常只需要一个外观类,并且此外观类只有一个实例,换言之,它是一个单例类。在很多情况下为了节约系统资源,一般将外观类设计为单例类。当然这并不意味着在整个系统里只能有一个外观类,在一个系统中可以设计多个外观类,每个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能。 - 不要试图通过外观类为子系统增加新行为
不要通过继承一个外观类在子系统中加入新的行为,这种做法是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增加应该通过修改原有子系统或增加新的子系统来实现,不能通过外观类来实现。 - 外观模式与迪米特法则
外观模式创造出一个外观对象,将客户端所涉及的属于一个子系统的协作伙伴的数量减到最少,使得客户端与子系统内部的对象的相互作用被外观对象所取代。外观类充当了客户类与子系统类之间的“第三者”,降低了客户类与子系统类之间的耦合度,外观模式就是实现代码重构以便达到”迪米特法则“要求的一个强有力的武器 - 抽象外观类的引入
外观模式最大的缺点在于违背了”开闭原则“,当增加新的子系统或者移除子系统时需要修改外观类,可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。
小结
外观模式比较简单理解,它通过与门面打交道,避免了与下面各个复杂子系统的操作,从而达到简化系统的目的,让这个复杂的系统变得容易使用。如果能够合理的使用外观模式,可以帮助我们更好的划分访问的层次,隐藏一些复杂细节到子系统,留个简单粗暴的接口给外观展示,外观模式,就这么简单!