重学设计模式(三设计模式-外观模式)
Posted 穆瑾轩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重学设计模式(三设计模式-外观模式)相关的知识,希望对你有一定的参考价值。
1、外观模式
面向对象编程的最大优势,在于它能够防止应用程序成为混乱的小块程序。当我们的应用程序和复杂库或框架的大量对象一起工作,通常需要初始化这些对象,并引入相应的依赖关系,以正确的执行方法。这样你的类的业务将与第三方库或框架的实现细节紧密的耦合,使其难以理解和维护。外观模式就是用来解决这个问题的。
1.1、什么是外观模式
-
定义
外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供统一的入口,封装子系统的复杂性,便于客户端调用。
外观(Facade)模式是“迪米特法则”的典型应用,在日常编码工作中,我们都在有意无意的大量使用外观模式。
只要是高层模块需要调度多个子系统(这里的子系统可以是一个完整的系统,也可以是模块或者更细粒度的类的对象),我们都会自觉地创建一个新的类封装这些子系统,提供精简的接口(只暴露有限的必要接口),让高层模块可以更加容易地间接调用这些子系统的功能,说白了就是封装系统的底层实现,隐藏系统的复杂性,提供一组更加简单易用、更高层的接口。比如:我们平时写的一些Utils类(DButils)可以理解为Facade;Linux 系统调用函数,它封装了底层更基础的 Linux 内核调用。
外观模式的意图在于:为多个复杂的子系统提供统一的入口,来简化客户端的调用。
外观模式的结构:
1)外观(Facade)角色:为多个子系统对外提供一个共同的接口;
2)子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
3)客户(Client)角色:通过一个外观角色访问各个子系统的功能,而不是直接调用子系统。
1.2、外观模式的优缺点
-
优点
1)可以将代码与子系统的复杂性隔离开来,降低了子系统与客户端之间的耦合度;
2)屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
-
缺点
违背了“开闭原则”,增加新的子系统可能需要修改外观类或客户端的代码。
1.3、创建方式
我们可能经常会使用积分兑换一些物品,这里我们就以信用卡积分兑换为例。客户可能会选择兑换的礼品,我们首先会校验是否能兑换,然后扣除积分兑换成功,最后进入物流系统等待收货。
1)先声明礼品信息Gift
//礼品信息
public class Gift
private String name; //礼品名称
private Integer score; //积分
public Gift(String name,Integer score)
this.name = name;
this.score = score;
public String getName()
return name;
public Integer getScore()
return score;
2)积分验证子系统
//积分验证子系统,为了简便子系统一般实现接口
public class Verification
public boolean isAvailable(String custid,Gift gift)
//查询custid客户积分custScore
Integer custScore = 9999999;
if(custScore <gift.getScore())
System.out.println("您的积分不足,无法兑换");
return false;
System.out.println("积分校验成功,积分可以兑换");
return true;
3)积分支付子系统
//积分支付子系统,为了简便子系统一般实现接口
public class PayScore
public boolean pay(String custId,Gift gift)
//custId获取客户信息,积分totalScore
//扣除客户积分:totalScore - gift.getScore();
System.out.println("积分扣减成功");
return true;
4)物流子系统
//物流子系统,为了简便子系统一般实现接口
public class Logistics
public boolean SendLogistics(String custid,Gift gift)
System.out.println(custid+"的礼品:"+gift.getName()+"-物流发送成功");
return true;
5)当没有使用外观规模,客户端的调用过程,比较复杂
//没有使用外观模式的客户端
public class Client
public static void main(String[] args)
String custid = "1号客户";
Gift gift = new Gift("微波炉",999);
//积分校验
Verification vf = new Verification();
if(!vf.isAvailable(custid,gift))
return;
//支付积分
PayScore ps = new PayScore();
ps.pay(custid, gift);
//物流发送
Logistics ls = new Logistics();
ls.SendLogistics(custid, gift);
6)使用外观模式(门面模式)
public class jfSystemFacade
//复习下,聚合是has-a关系,整体与部分关系弱,组合是contains-a关系,整体与部分关系强
private Verification vf;
private PayScore ps;
private Logistics ls;
public jfSystemFacade()
vf = new Verification();
ps = new PayScore();
ls = new Logistics();
public boolean ScoreExchange(String custid,Gift gift)
//积分校验
if(!vf.isAvailable(custid,gift))
return false;
//支付积分
ps.pay(custid, gift);
//物流发送
ls.SendLogistics(custid, gift);
return true;
7)此时的客户端
//使用外观模式的客户端,客户端的调用精简了很多
public class Client
public static void main(String[] args)
String custid = "1号客户";
Gift gift = new Gift("微波炉",999);
jfSystemFacade fd = new jfSystemFacade();
fd.ScoreExchange(custid, gift);
此时的UML关系图:
1.4、总结及建议
外观模式更像是客户端应用程序的助手,其本质就是整合接口,封装低层实现细节,为客户端提供一个更简洁的接口,实现了子系统与客户端间的松耦合关系。
应用场景:
1)当您需要一个有限但直接的接口来连接复杂的子系统时,可以使用外观模式;
2)当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。
3)防止客户端将对象转换为更底层的真实对象,隐藏底层不必要暴露给客户端的一些方法或属性。
JDK中外观模式的应用:
在java类库中直接使用门面模式的并不多,作为java开发者,通常需要对类库中的工具做整体的了解,外观模式可能会使得类库变得复杂,让人使用者产生误解。
不过在Tomcat中就有大量的外观模式的应用。因为Tomcat中有很多不同组件,每个组件要相互通信,但是又不能将自己内部数据过多的暴露给其他组件。
org.apache.catalina.connector.HttpRequestFacade
org.apache.catalina.connector.HttpResponseFacade
以上是关于重学设计模式(三设计模式-外观模式)的主要内容,如果未能解决你的问题,请参考以下文章