设计模式系列之七:外观模式

  1. 云栖社区>
  2. 博客>
  3. 正文

设计模式系列之七:外观模式

rhwayfun 2016-03-27 21:58:00 浏览845
展开阅读全文

前言

外观模式属于设计模式中的结构型设计模式,所谓结构型,就是说外观模式更关注的系统的架构设计。使用外观模式使得子系统间的依赖达到最小,通过设置一个Facade外内外提供了了简单的屏障。外观模式为一组接口提供一个统一的界面,这个界面就是这组接口的高级接口,这个高级接口使得子系统更加易用。通常在软件设计中,尤其是OO,对实现细节的过多暴露是很不利于后期的扩展的。只有暴露的细节越少,进行功能的扩展才会更加容易。外观相当于一个门面,是与外界进行沟通交流的,相当于公司的业务员,业务员每天都要与很多客户打交道;而具体的子系统则相当于开发功能模块的开发人员,不需要与具体的客户沟通推销产品,只负责功能的实现以及产品的交付,是对内的。使用外观模式的好处就是外界只需要有一个Facade就行了,这个Facade能够与外界进行各种交付,当需要某个子系统的功能时,Facade从内部进行调用就行。

通常使用外观模式是这样的:

外观模式

从这张图可以看出,在使用外观模式之前,外界(每个具体的客户)需要了解子系统的具体功能模块,而一旦子系统发生更改,则与外界的交付将无法进行下去,这样显然系统与外界的耦合程度很高,每次交付都要依赖具体的子系统。而现在使用Facade之后,客户类只需要与一个Facade进行交付就可以了,显然更省心省力,而且当子系统发生更改,客户类也不需要知道发生了什么更改,因为Facade知道哪个系统发生了更改,进行了什么更改。这一点在原有复杂系统的基础上开发新的功能模块很有用,在开发过程中,可以使用一个Facade与老系统进行交付,使用另一个Facade进行新功能模块的开发,明显是很有优势的。

外观模式为子系统提供了对外访问的高级接口,这个接口知道所有子系统的实现细节,当外界访问相关的功能时,Facade会指派一个子系统完成具体的功能。从这点来看外观模式与代理模式有一些类似,那么两者有什么区别呢?

  1. 代理对象主要代表一个对象,而外观模式的Facade则代表一个子系统
  2. 代理对象无法直接直接目标对象,只是提供访问对象的访问控制(不让目标对象与外界进行交付,而是由代理对象完成与外界的交互);而外观对象可以直接访问目标对象,但是对目标对象的访问是以更高级的接口完成调用的。

编码实践一

下面以股民买卖股票作为例子说明外观模式的运用

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

public class Stock2{
    //买股票
    public void buy(){System.out.println("股票2买入");}
    //卖股票
    public void sell(){System.out.println("股票2卖出");}
}

public class NationalDebt{
    //买国债
    public void buy(){System.out.println("国债买入");}
    //卖国债
    public void sell(){System.out.println("国债卖出");}
}

public class Test{
    public static vois main(String[] args){
        Stock1 s1 = new Stock1();
        Stokc2 s2 = new Stock2();
        NationalDebt nd = new NatationalDebt();

        s1.buy();
        s2.buy();
        nd.buy();

        s1.sell();
        s2.sell();
        nd.sell();
    }
}

代码很好理解,而不足之处在于客户端需要关心每只股票的买入与卖出,这样当股票的数目很多的时候,对于股民来讲简直就是灾难,因为毕竟人的精力是有限的。下面我们通过外观模式解决这个问题

编码实践二

//增加基金类,相当于我们的Facade门面
public class Fund{
    private Stock1 s1;
    private Stock2 s2;
    private NationalDebt nd;

    public Fund(){
        s1 = new Stcok1();
        s2 = new Stock2();
        nd = new NationalDebt();
    }

    //买入基金,这个方法相当于帮客户封装了所有的股票信息,这个方法会帮股民去分析该买入哪个卖出哪个
    public void buy(){
        s1.buy();
        s2.buy();
        nd.buy();
    }
    //卖出基金
    public void sell(){
        s1.sell();
        s2.sell();
        nd.sell();
    }
}

这样,通过Facade对象,客户完全不用关心该买那只股票以及该卖出哪只股票,Facade会自动分析未来股票的涨跌趋势,从而帮助客户做出买卖股票的决定,而我们这里的Fund类就相当于我们的门面,外界通过这个对象与系统进行交互。

网友评论

登录后评论
0/500
评论
rhwayfun
+ 关注