二、外观模式(Facade)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lzx_longyou/article/details/51636128

2.1 场景问题

2.1.1 生活中的示例

    生活中组装电脑通常有方案。第一种,是到电子市场把自己所需的配件买回来自己组装,需要对各个配件都比较属性,才能选择最合适的配件,而且要考虑配件之间兼容性。第二种,是到电子市场找一家专业的装机公司,提出具体需求,让他们帮你组装,我们只需等着拿电脑。
    这个专业的装机公司就相当于“外观模式”。将上面所述的电脑配件抽象成模块,第一种方案,客户就需要对各个模块都熟悉,了解其功能才能做出选择;第二种方案,客户只需要与装机公司这个“外观模式”打交道,不需要了解各个模块的细节功能,不用跟系统各个模块交互,这样就显得更加简单了。
    如何实现,才能让子系统外部的客户端在使用子系统的时候,既能简单地使用这些子系统内部的模块功能,而又不用客户端去与子系统内部的多个模块交互呢? 使用外观模式可以解决这样的问题。

2.2 解决方案

2.2.1 使用外观模式来解决问题

1. 外观模式的定义
    为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。这里所说的接口,并不等价于interface,主要是指外部和内部交互的一个通道,可以是类的方法,也可以是interface的方法。
2. 应用外观模式来解决问题的思路
    外观模式就是引入一个外观类,在这个类里面定义客户端想要的简单的方法,然后在这些方法的实现里面,由外观类再去调用内部的多个模块来实现功能,从而让客户端变得简单,这样客户端只要和外观类交互就可以了。

2.2.2 外观模式示例代码

外观模式实例的整体结构示意图:


示例代码:
public interface AModuleApi {
	/**
	 * A模块对外的一个功能方法
	 */
	public void testA();
}

public class AModuleImpl implements AModuleApi {

	@Override
	public void testA() {
		System.out.println("现在在A模块里操作testA方法");
	}

}

public interface BModuleApi {
	/**
	 * B模块对外的一个功能方法
	 */
	public void testB();
}

public class BModuleImpl implements BModuleApi {

	@Override
	public void testB() {
		System.out.println("现在在B模块里操作testB方法");
	}

}

public interface CModuleApi {
	/**
	 * C模块对外的一个功能方法
	 */
	public void testC();
}

public class CModuleImpl implements CModuleApi {

	@Override
	public void testC() {
		System.out.println("现在在C模块里操作testC方法");
	}

}

/**
 * 外观对象
 */
public class Facade {
	public void test() {
		//在内部实现的时候,可能会调用到内部的多个模块
		AModuleApi a = new AModuleImpl();
		a.testA();
		
		BModuleApi b = new BModuleImpl();
		b.testB();
		
		CModuleApi c = new CModuleImpl();
		c.testC();
	}
}

public class Clinet {
	public static void main(String[] args) {
		new Facade().test();
	}
}

2.3 模式讲解

2.3.1 认识外观模式

1. 外观模式的目的
    外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内部多个模块的交互,松散耦合,从而让外部能够更简单地使用子系统。
2. 使用外观和不使用外观相比有何变化
    表面上看就是把客户端的代码搬到Facade里面了,但实质是发生了变化。Facade位于A、B、C模块组成的系统这边,而不是位于客户端。因此,它相当于屏蔽了外部客户端和系统内部模块的交互,从而把A、B、C模块组合成一个整体对外,不但方便了客户端的调用,而且封装了系统内部的细节功能。如果今后调用模块的算法发生了变化,只需要修改Facade的实现就可以了。
    另一个优点是,Facade的功能被多个客户端调用,实现了功能的共享,实现了复用。

2.3.2 外观模式的优缺点

1. 松散耦合:外观模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。
2. 简单易用:外观模式让子系统更加易用,客户端不在需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟外观交互就可以。
3. 更好地划分访问的层次:有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观中,这样既方便客户端使用,也很好的隐藏了内部细节。

2.3.3 思考外观模式

1. 外观模式的本质:封装交互,简化调用
2. 对设计原则的体现:最少知识原则。
    如果不使用外观模式,客户端通常需要和子系统内部的多个模块交互,于是客户端和这些模块就有依赖关系,任意一个模块的变动都会引起客户端的变动。
    使用外观模式后,客户端只需要和外观类交互,客户端不需要关心子系统内部模块的变动情况,客户端只是和这个外观类有依赖关系。可以在不影响客户端的情况下,实现系统内部的维护和扩展。
3. 何时选择外观模式
    如果希望为一个复杂的子系统提供一个简单的接口,可以考虑使用外观模式。使用外观对象来实现大部分客户需要的功能,从而简化客户的使用。
    如果想要让客户程序和抽象类的实现部分松散耦合,可以考虑使用外观模式。使用外观对象来讲这个子系统与它的客户分开,从而提供子系统的独立性和可移植性。
    如果构建多层结构系统,可以考虑使用外观模式,使用外观对象作为每层的入口,这样可以简化层间调用,也可以松散层次之间的依赖关系。


猜你喜欢

转载自blog.csdn.net/lzx_longyou/article/details/51636128
今日推荐