一、门面模式

1、定义

GOF《设计模式》一书对Facade模式是这样描述的:

为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子系统更加容易使用。

2、结构

    门面角色:客户端可以调用这个角色的方法。此角色知道子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统中去。

    子系统角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。

3、适用性

   (1) 不需要使用一个复杂系统的所有功能,而且可以创建一个新的类,包含访问系统的所有规则。如果只需要使用系统的部分功能,那么你为新类所创建的API将比原系统的API简单的多。

   (2) 希望封装或者隐藏系统原系统。

   (3) 希望使用原系统的功能,而且还希望增加一些新的功能。

   (4) 编写新类的成本小于所有人学会使用或者未来维护原系统上所需的成本。

二、使用范例

     下面以到商店买东西为例,一般情况下,我们要买东西都是直接到商店去买,而不是到生产产品的工厂去买,这里的商店就可以看成是一个门面,然后工厂就是一个一个的子系统,当你需要什么货品时,直接去商店买就是了,不用管工厂的事,商店来根据你要的产品,选择不同的工厂来进货。

package com.model.facade;
/**
 * 一个香皂类
 */
class Coat{
	public String toString(){
		return "香皂一个";
	}
}
/**
 * 生产香皂的厂家
 */
public class CoatFactory {
	/**
	 * 厂家卖香皂
	 */
	public Coat saleCoat(){
		return new Coat();
	}

}

 

package com.model.facade;
/**
 * 电脑类
 */
class Computer{
	public String toString(){
		return "电脑一台";
	}
}
/**
 * 生产电脑的厂家
 */
public class ComputerFactory {
	/**
	 * 卖电脑
	 */
	public Computer saleComputer() {
		return new Computer();
	}
}
package com.model.facade;
/**
 * 水果类
 */
class Fruit{
	public String toString(){
		return "水果一箱";
	}
}
/**
 * 生产水果的厂家
 */
public class FruitFactory {
	/**
	 * 卖水果
	 */
	public Fruit saleFruit(){
		return new Fruit();
	}
	
}

商店来了:

package com.model.facade;
/**
 * 商店,专门来买进工厂的东西,然后卖给客户
 */
public class Store {
/**
 * 商店卖香皂
 */
public Coat saleCoat(){
	CoatFactory m_CoatFactory=new CoatFactory();
	return m_CoatFactory.saleCoat();
}
/**
 * 商店卖电脑
 */
public Computer saleComputer(){
	ComputerFactory m_Computer=new ComputerFactory();
	return m_Computer.saleComputer();
}

/**
 * 商店卖水果
 */
public Fruit saleFruit(){
	FruitFactory m_FruitFactory=new FruitFactory();
	return m_FruitFactory.saleFruit();
}

}

顾客来了:

package com.model.facade;
/**
 * @author 林炳文
 * @time 2015.2.10
 * 门面模式讲解
 */
public class Main {

	public static void main(String[] args) {
		Store m_Store=new Store();
		//买衣服  
        System.out.println("顾客买到:"+m_Store.saleCoat());  
        //买电脑  
        System.out.println("顾客买到:"+m_Store.saleComputer());  
        //买水果
        System.out.println("顾客买到:"+m_Store.saleFruit());  

	}

}

结果:

顾客买到:香皂一个
顾客买到:电脑一台
顾客买到:水果一箱

三、优缺点

1、优点

   (1)对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。

   (2)实现了子系统与客户之间的松耦合关系,这使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。

  (3)降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。

  (4)只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。

2、缺点

      (1)不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。

  (2)在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

总结

    Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Facade很多时候更是一种架构设计模式。Facade更注重简化接口,Adapter模式注重转换接口,Bridge模式注重分离接口(抽象)与其实现,Decorator模式注重稳定接口的前提下为对象扩展功能。