设计模式之外观模式(结构型)

386人阅读 评论(0) 收藏 举报
分类:

外观模式是我们平时使用频率很高的一种模式,我们在平常的开发中也会不经意的使用外观模式;外观模式是为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一子系统更加容易调用。

结构


这个外观类为子系统提供一个共同的对外接口
Clients
客户对象通过一个外观接口读写子系统中各接口的数据资源。

优点


(1)实现了子系统与客户端之间的松耦合关系。
(2)客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。

缺点


外观模式最大的缺点在于违背了“开闭原则”
当增加新的子系统或者移除子系统时需要修改外观类,可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。 

外观模式的构成


外观角色(Facade):是模式的核心,他被客户client角色调用,知道各个子系统的功能。同时根据客户角色已有的需求预订了几种功能组合\
子系统角色(Subsystem classes):实现子系统的功能,并处理由Facade对象指派的任务。对子系统而言,facade和client角色是未知的,没有Fac ade的任何相关信息;即没有指向Facade的实例。
客户角色(client):调用facade角色获得完成相应的功能。

适用场景


在遇到以下情况使用facade模式
    1) 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。
    这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。facade可以提供一个简单的缺省视图,
    这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过facade层。
    2) 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入 facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性 和可移植性。
    3) 当你需要构建一个层次结构的子系统时,使用 facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们之间的依赖关系。

示例


平常我们做程序员的有一部分人是炒股的,但是大家都知道炒股的风险很大。那么怎么办了,有些人会去选择一些风险比较小的基金;其实基金会买几十支好的锅,不会因为某个股票的大跌而影响收益,尽管每个人的钱不多,但大家放在一起,反而容易达到很好的投资效果;其实我们股民是不知道他里面具体做了什么,只知道基金涨或者是跌了;这样就解耦了股民和股票之间的耦合性;

/*/
 * 股票类
 */
public class Stock1 {
	public void buy(){
		System.out.println("买股票");
	}
	public void sell(){
		System.out.println("卖股票");
	}
}

/*/
 * 国债类
 */
public class Stock2 {
	public void buy(){
		System.out.println("买国债");
	}
	public void sell(){
		System.out.println("卖国债");
	}
}

还有一个房地产跟上面的相同,就不列举出来了,这个是基金的子类;他与基金类现在还没有任何关系,这三个子类也没有任何关系;
现在我们创建基金类,通过组合的方式将他们耦合到一起;
public class Fund {
	Stock1 stock1;
	Stock2 stock2;
	Stock3 stock3;
	
	public Fund(){
		stock1=new Stock1();
		stock2=new Stock2();
		stock3=new Stock3();
	}
	//买基金
	public void byfFund(){
		stock1.buy();
		stock2.buy();
		stock3.buy();
	}
	//卖基金
	public void sellFund(){
		stock1.sell();
		stock2.sell();
		stock3.sell();
	}
}

这样我们客户端调用的时候只需要调用基金类就OK了;
public static void main(String[] args) {
		Fund fund=new Fund();
		fund.byfFund();
		fund.sellFund();
	}

实例


这里说一个平常项目中用到的facede方法,我们大家开发一般都是用springMVC三层架构去实现,在service层去处理我们的业务,在dao层去访问数据库,在view层做视图展现。然而现在的项目是越做越复杂,普通的MVC已经满足不了我们的需求了,比如面临一个很复杂的页面,我们返回的VO可能需要做一些扩展;这个时候我会在action这一层加上一个facade;我们把facade又称为门面模式;在这里面我会去处理一些数据;比如把加上默认日期;拼接显示数据,数据转换等等;然后把这个facade返回给我们的视图;

总结:
外观模式一般都是单例的,但并不意味着一个类只能使用一个外观模式,也不意味着要把所有的外观模式都写在同一个类里面;
根据“单一职责原则”,在软件中将一个系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统的访问提供了一个简单而单一的入口。

外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以降低原有系统的复杂度,外观类充当了客户类与子系统类之间的“第三者”,同时降低客户类与子系统类的耦合度。外观模式就是实现代码重构以便达到“迪米特法则”要求的一个强有力的武器。

在软件设计初期阶段,应该要有以为的将不同的两个层分离,重构的时候在可以通过增加外观facade提供一个简单的接口,减少他们的依赖;这样使用外观模式感觉比较好一点;





1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:327245次
    • 积分:5204
    • 等级:
    • 排名:第5904名
    • 原创:160篇
    • 转载:40篇
    • 译文:8篇
    • 评论:110条
    博客专栏
    最新评论
    spring学习之路
    开始重新学习spring了,记录自己的点点滴滴,加油吧,少年。