- 外观模式:
为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得子系统更加容易调用。
从外观模式的定义中可以了解到,其实外观模式相当于一个中间人,比如说你要去酒店吃饭,你并不需要知道菜的做法,不需要知道菜的清洗过程,也不需要知道菜的来源。你只需要喊上服务员和他说我要吃什么就可以了,这里的服务员其实就相当于一个外观角色,也就是一个更高层的接口。而饭店中的各种菜就相当于一个一个子系统。 - 外观模式的示意图:
- 外观模式包含的角色:
外观角色: 这是外观角色的核心类,一般情况下,外部的客户端可以调用这个类里面的方法,而这个类又清楚一个或多个子类的功能,因此,他可以将外部发来的请求,传递给到合适的子类去执行。
子系统角色: 这个角色有一个或者多个。每个子系统既可以被外观角色调用,又可以被外部系统调用。并不是说,有个外观角色后子系统就不能被外部客户端调用了,这点要注意。外部系统还是可以跳过外观角色自己去调用子系统。 - 外观角色示例代码:
场景:假设去酒店吃饭,点了麻婆豆腐和红烧肉。你只需要和服务员说你需要这两个就可以了,不需要知道做法,清洗过程,以及菜的原料的来源
子系统类:
红烧肉:
public class HongShaoRou {
private static HongShaoRou instance = null;
private HongShaoRou() {
}
public static HongShaoRou getInstance(){
if (instance==null){
instance = new HongShaoRou();
}
return instance;
}
public void get(){
System.out.println("去菜市场肉店店买原材料<<<<<<");
}
public void wash(){
System.out.println("清洗原材料<<<<<<");
}
public void cook(){
System.out.println("烹饪<<<<<<");
}
}
麻婆豆腐:
public class MaPoDouFu {
private static MaPoDouFu instance = null;
private MaPoDouFu() {
}
public static MaPoDouFu getInstance(){
if (instance==null){
instance=new MaPoDouFu();
}
return instance;
}
public void get(){
System.out.println("去菜市场豆腐店买原材料<<<<<<");
}
public void wash(){
System.out.println("清洗原材料<<<<<<");
}
public void cook(){
System.out.println("烹饪<<<<<<");
}
}
服务员(外观角色):
public class Waiter {
public void order(){
HongShaoRou hongShaoRou = HongShaoRou.getInstance();
MaPoDouFu maPoDouFu = MaPoDouFu.getInstance();
maPoDouFu.get();
hongShaoRou.cook();
}
}
测试主函数:
public class Main {
public static void main(String[] args) {
Waiter waiter = new Waiter();
waiter.order();
MaPoDouFu maPoDouFu = MaPoDouFu.getInstance();
maPoDouFu.get();
}
}
从测试主函数中,可以看出,有了外观角色并不妨碍客户端去独立的调用子系统。
5. 外观模式的优缺点
优点:
- 外观模式为客户端屏蔽了一部分子系统,减少了客户端所需要处理的类的对象,这样在一定程度上简化了客户端的代码。
- 松耦合,将客户端和子系统之间的耦合降到很低的程度,在这种情况下,子系统发生变化,不会影响客户端,只需要调整外观角色即可。
- 子系统之间相互独立,互不影响。
缺点: - 违背了开闭原则,修改子系统可能要修改外观类
- 外观模式的使用场景
- 当客户端需要调用一系列复杂子系统时候,可以提供一个简单入口的时候使用外观模式。
- 需要将客户端与子系统解耦
- 在层次化结构中可以使用外观模式定义系统中的每一层的入口,层与层之间不直接产生联系。而通过外观类产生联系。其实也就是解耦合。