门面模式很简单而且我们就在使用,废话不多说直接上类图。
关注Client类和Facad类还有subsystem即可。
OK,是不是觉得似曾相识,哈哈一会解答。先捋一捋门面的作用,从类图上来看我们外部的Client都需要通过访问Facad类才可以访问到subsystem。
很简单的模式,我不过多做解释了,先码代码。一看就明白了。
一股脑码在一起看完再解释,很简单。
/**
* 商品系统
* @author liyichen
*
*/
public class GoodsSystem {
public void showAllGoods() {
System.out.println("展示所有的商品.....");
}
}
/*---------------------------------------分割线---------------------------*/
/**
* 订单系统
* @author liyichen
*
*/
public class OrderSystem {
public void createOrder() {
System.out.println("订单被创建...");
}
}
/**
* 门面类
* @author liyichen
*
*/
public class Facade {
private OrderSystem s1 = new OrderSystem();
private GoodsSystem s2 = new GoodsSystem();
public void createOrder() {
s1.createOrder();
}
public void showAllGoods() {
s2.showAllGoods();
}
}
public class Client {
public static void main(String[] args) {
Facade f = new Facade();
f.createOrder();
}
}
OK,看明白了吗?我们整理一下:
1.客户端类只知道有门面的存在,对于客户端来说门面就是一个服务类,门面的角色对客户端类是无感知的 ;
2.对于真正的服务类来讲,门面类也是Client的存在,门面的角色同样对服务类无感知;
3.客户端类只能通过门面才能访问到服务类,门面只是委托的角色不参与任何业务逻辑。
我们来看一段代码,分析这个门面类设计的是否合理?
/**
* 门面类
* @author liyichen
*
*/
public class Facade {
private OrderSystem s1 = new OrderSystem();
private GoodsSystem s2 = new GoodsSystem();
public void createOrder() {
s1.createOrder();
}
public void showAllGoods() {
s2.showAllGoods();
}
public void shopping() {
s2.showAllGoods();
s1.createOrder();
}
}
我们将门面类稍作修改,此时的shooping方法需要 s1和s2共同来完成。那这样的设计是否合理呢?
其实问题的答案我们在上面已经给出了,门面类不参与任何逻辑,只是委托服务。而现在的shooping方法已经在参与逻辑了,此时出现一个倒依赖的问题,客户端类必须通过门面才能完成业务逻辑。破坏系统的封装性,是一个错误的设计。
那正确的做法应该再提供出一个服务类,由它去操作逻辑,而门面只是作为委托的角色。
修改后如下:
public class Facade {
private OrderSystem s1 = new OrderSystem();
private GoodsSystem s2 = new GoodsSystem();
private Shopping s3 = new Shopping();
public void createOrder() {
s1.createOrder();
}
public void showAllGoods() {
s2.showAllGoods();
}
public void shopping() {
s3.shopping();
}
}
那我们再来想想门面给我们带来了什么好处?
1.安全性,大家都必须访问同一个入口才能得到结果。
2.减少依赖,客户端只需要知道门面即可。
同样的门面也有不足之处,他可能会特别臃肿,所以在适当情况吓可以根据模块再拆分不同的门面。
我们常用的网关啊,NGINX等等,他们不就是门面模式吗?哈哈学习了吗?不足之处欢迎指正。