设计模式之外观模式(Facade)

1.外观模式的概念

外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用,它是一种对象结构型模式。

2.外观模式的结构图

设计模式之外观模式(Facade)_第1张图片
Facade类:外观类,知道哪些子系统类负责处理请求,将客户的请求代理给适当的子系统对象。
SubSystem Classes:子系统类集合,实现子系统的功能,处理Facade对象指派的任务。注意子类中没有Facade对象指派的任务。注意子类中没有Facade的任何信息,即没有对Facade对象的引用。每一个子系统都可以被客户端直接调用,或者被Facade直接调用。子系统并不知道Facade的存在,对于子系统而言,Facade仅仅是另一个客户端而已。

3.外观模式的例子

  假设一个股民买了四支股票,分别为股票一、股票二、国债股和房地产股,然后这个股民要对这四个股票进行买入和赎回的操作,如果要使用一般的方法进行操作,那么操作代码如下:
Stock1类(具体股票一类):

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 *
 * 股票1
 */
public class Stock1 {

    // 卖股票
    public void sell() {

        System.out.println("股票1卖出");
    }

    // 买股票
    public void buy() {

        System.out.println("股票1买入");
    }
}

Stock2(具体股票二类):

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 * 

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

NationalDebt1类(具体国债类):

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 * 

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

Realty1类(具体房地产类):

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 * 

* 房地产1 */ public class Realty1 { // 卖房地产 public void sell() { System.out.println("房地产1卖出"); } // 买房地产 public void buy() { System.out.println("房地产1买入"); } }

客户端:

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 */
public class Client {

    public static void main(String[] args) {

        Stock1 s1 = new Stock1();
        Stock2 s2 = new Stock2();
        NationalDebt1 n1 = new NationalDebt1();
        Realty1 r1 = new Realty1();

        s1.buy();
        s2.buy();
        n1.buy();
        r1.buy();

        s1.sell();
        s2.sell();
        n1.sell();
        r1.sell();
    }

}

运行结果:

股票1买入
股票2买入
国债1买入
房地产1买入
股票1卖出
股票2卖出
国债1卖出
房地产1卖出

Process finished with exit code 0

  虽然这样做也满足了需求,但是我们可以看到在客户端中要创建大量的对象,并且需要具体参与每支股票的买卖,耦合性很高。我们完全可以让这个股民买一致基金,让这个基金去管理这些股票,这个股民无需关注每支股票到底要怎么样操作,他只需要买了基金,让基金去管这些,他只用抽烟喝酒烫头就行了,过段时间再赎回基金就可以有大把的money,此时客户端就可以非常简洁。要想达到这样的效果,就要使用我们的外观模式啦。
  
我们先来看看这个例子的结构图:
设计模式之外观模式(Facade)_第2张图片
然后使用代码来实现:
具体的股票类上面代码已经给出,这里不再重复。
Fund类(基金类):

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 */
public class Fund {

    Stock1 s1;
    Stock2 s2;
    NationalDebt1 n1;
    Realty1 r1;

    public Fund() {

        s1 = new Stock1();
        s2 = new Stock2();
        n1 = new NationalDebt1();
        r1 = new Realty1();
    }

    public void buyFund() {

        s1.buy();
        s2.buy();
        n1.buy();
        r1.buy();
    }

    public void sellFund() {

        s1.sell();
        s2.sell();
        n1.sell();
        r1.sell();
    }
}

客户端:

package com.jxs.facade;

/**
 * Created by jiangxs on 2018/5/7.
 */
public class Client {

    public static void main(String[] args) {

        Fund fund = new Fund();
        // 基金购买
        fund.buyFund();
        // 基金赎回
        fund.sellFund();
    }

}

运行结果:

股票1买入
股票2买入
国债1买入
房地产1买入
股票1卖出
股票2卖出
国债1卖出
房地产1卖出

Process finished with exit code 0

4.外观模式的总结

(1)外观模式的优点

①引入外观模式,是客户对子系统的使用变得简单了,减少了与子系统的关联对象,实现了子系统与客户之间的松耦合关系。
②只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。
③降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程。

(2)外观模式的缺点

①不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。
②在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

(3)外观模式的适用场景

①在设计初期阶段,应该有意识的将不同的两个层分离。比如经典的MVC三层架构,就需要考虑在Control层和Model层,Model层和View层的层与层之间建立外观Facade,这样就可以为复杂子系统提供一个简单的接口,使得耦合大大降低。
②在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
③在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含了非常重要的功能,新的需求开发必须要依赖于它。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。

注:
以上代码均可在github上进行下载:https://github.com/xsongj/designPattern

参考:《大话设计模式》

你可能感兴趣的:(设计模式,最详细的设计模式,设计模式,外观模式,门面模式,Facade)