【JAVA设计模式】外观模式(Facade Pattern)

一  定义

为子系统中的一组接口提供一个一致的界面。Facade模式定义了一个高层的接口,这个接口使得这一子系统更加easy使用。

二  案例

一个子系统中拥有3个模块。每一个模块中都有3个方法。当中一个为client调用方法,其它两个则为各子模块间互相调用方法。此时有例如以下需求,client为完毕功能。须要组合3个模块中的方法才干实现功能。

三  未使用模式情况

/**
 * @Description A模块
 * @author jerry
 * @date 2016年4月11日下午2:16:04
 */
public interface AModuleApi {
	public void a1();	//此方法主要用于外部调用
	public void a2();	//下面双方法主要用于子系统内部间调用
	public void a3();
}
/**
 * @Description A模块实现
 * @author jerry
 * @date 2016年4月11日下午2:17:10
 */
public class AModuleImpl implements AModuleApi {

	@Override
	public void a1() {
		System.out.println("调用了A模块");
	}

	@Override
	public void a2() {
		//TODO 主要用于子模块间互相调用
	}

	@Override
	public void a3() {
		//TODO 主要用于子模块间互相调用
	}
}
/**
 * @Description B模块
 * @author jerry
 * @date 2016年4月11日下午2:16:12
 */
public interface BModuleApi {
	public void b1();	//此方法主要用于外部调用
	public void b2();	//下面双方法主要用于子系统内部间调用
	public void b3();
}
/**
 * @Description B模块实现
 * @author jerry
 * @date 2016年4月11日下午2:17:10
 */
public class BModuleImpl implements BModuleApi {

	@Override
	public void b1() {
		System.out.println("调用了B模块");
	}

	@Override
	public void b2() {
		//TODO 主要用于子模块间互相调用
	}

	@Override
	public void b3() {
		//TODO 主要用于子模块间互相调用
	}
}

同理。C模块也是如此,篇幅原因。这里不贴代码了,须要代码能够从我github下clone,文末会给出地址。

client调用例如以下:

public class Client {

	public static void main(String[] args) {
		AModuleApi a = new AModuleImpl();
		a.a1();
		BModuleApi b = new BModuleImpl();
		b.b1();
		CModuleApi c = new CModuleImpl();
		c.c1();
	}
}

相信非常easy能够写出这种代码。

细致想想能够发现,假设这样写。会存在例如以下问题:

  1. 代码耦合度太高,client与子系统中各模块都有关联。一旦子系统有什么更改,会涉及到client的改动。
  2. 对client学习成本太高。client须要学习各个模块中每一个public方法。知道其什么含义后才干进行调用。

四  使用模式的情况

我们能够在系统这端(即外观模式属于系统这端,若属于客户这端。仍然须要客户去了解每一个模块每一个方法意义,这样无不论什么意义。) 加入一个外观类,由外观类重组须要调用的方法,例如以下所看到的:

/**
 * @Description 外观类,通常设计成单例
 * @author jerry
 * @date 2016年4月11日下午2:43:26
 */
public class Facade {
	private Facade(){}

	public static void test(){
		AModuleApi a = new AModuleImpl();
		a.a1();
		BModuleApi b = new BModuleImpl();
		b.b1();
		CModuleApi c = new CModuleImpl();
		c.c1();
	}
}
public class Client {

	public static void main(String[] args) {
//		AModuleApi a = new AModuleImpl();
//		a.a1();
//		BModuleApi b = new BModuleImpl();
//		b.b1();
//		CModuleApi c = new CModuleImpl();
//		c.c1();

		Facade.test();
	}
}

这样一来。client仅仅要与外观类打交道就可以,从而更好地实现了client和子系统各模块的耦合性。

使用外观的目的: 不是给子系统加入新的功能接口,而是让外部降低对子系统内部多个模块的直接交互。松散耦合,从而可以让外部更简单地使用子系统。

当然有时你会有这种需求,client可能仅仅须要调用两个模块就可以,那么现有的外观模式就无法使用了,仅仅好绕开外观类。直接找各模块进行调用。此外,你是否发现。我的ABC模块里面除了有供外部调用的方法外。还有各模块间互相调用的方法,这些方法本不须要client了解。暴露了过多内部细节。会让client产生疑惑,这就是“接口污染” 
。要解决问题,我们能够将Facade类定义为接口,并对事实上现,使用工厂模式对其创建实例,例如以下所看到的:

public interface FacadeApi {
	public void a1();
	public void b1();
	public void c1();

	/**
	 * @Description 原有方法,将各模块方法组合调用
	 * @return void
	 * @throws
	 */
	public void test();
}
/**
 * @Description 外观接口实现
 * @author jerry
 * @date 2016年4月11日下午3:19:25
 */
public class FacadeImpl implements FacadeApi {

	@Override
	public void a1() {
		new AModuleImpl().a1();
	}

	@Override
	public void b1() {
		new BModuleImpl().b1();
	}

	@Override
	public void c1() {
		new CModuleImpl().c1();
	}

	@Override
	public void test() {
		a1();
		b1();
		c1();
	}
}
/**
 * @Description 外观接口实现
 * @author jerry
 * @date 2016年4月11日下午3:19:25
 */
public class FacadeImpl implements FacadeApi {

	@Override
	public void a1() {
		new AModuleImpl().a1();
	}

	@Override
	public void b1() {
		new BModuleImpl().b1();
	}

	@Override
	public void c1() {
		new CModuleImpl().c1();
	}

	@Override
	public void test() {
		a1();
		b1();
		c1();
	}
}
public class Client {

	public static void main(String[] args) {
//		AModuleApi a = new AModuleImpl();
//		a.a1();
//		BModuleApi b = new BModuleImpl();
//		b.b1();
//		CModuleApi c = new CModuleImpl();
//		c.c1();

//		Facade.test();

		FacadeApi api = Factory.createFacade();
		api.test();
	}
}

这样以后,就对client降低了模块内部方法的暴露。

五  总结

外观模式的本质:封装交互。简化调用

何时使用外观模式:

  1. 假设你希望为一个复杂的子系统提供一个简单接口
  2. 假设构建多层结构的系统。能够考虑使用外观模式,使用外观对象作为每层的入口,这样能够简化层间调用,能够减少耦合度。

------------------------------------------------------------------------------------------------------------------------------------------

Github:  https://github.com/jerry-sc/designPattern

Reference:《研磨设计模式》
时间: 2024-10-12 21:37:17

【JAVA设计模式】外观模式(Facade Pattern)的相关文章

设计模式 - 外观模式(facade pattern) 详解

外观模式(facade pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy 外观模式(facade pattern): 提供了一个统一的接口, 用来访问子系统中的一群接口. 外观定义了一个高层接口, 让子系统更容易使用. 外观模式包含三个部分: 1. 子系统: 子类, 单个复杂子类 或 多个子类; 2. 外观(facade)类: 把子系统设计的更加容易使用; 3. 客户: 只需要调用外观类. 与适配器模式(adapter pattern)的

二十四种设计模式:外观模式(Facade Pattern)

外观模式(Facade Pattern) 介绍为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 示例有一个Message实体类,某对象对它的操作有Get()方法,另外还有一个对象有一个Validate()方法来判断用户是否有权限.现在提供一个高层接口来封装这两个方法. MessageModel using System; using System.Collections.Generic; using System.Text; nam

设计模式-10外观模式(Facade Pattern)

1.模式动机 在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了. 软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂.这时如果系统内部发生改变,客户端也要跟着改变,这违背了"开闭原则",也违背了"迪米特法则(最少知道原则)",所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标. 2.模式定义 外观模式(F

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

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(结构型)之装饰者模式(Decorator Pattern)>http://blog.csdn.net/yanbober/article/details/45395747 概述 一个客户类需要和多个业务类交互,而这些业务类经常会作为整体出现,由于涉及到的类比较多,导致使

java设计模式--外观模式(Facade)

外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口,看下类图:(我们以一个计算机的启动过程为例) 我们先看下实现类: [java] view plain copy public class CPU { public void startup(){ System.out.println("cpu startup!"); } public v

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

什么是外观模式? 外观模式(Facade),为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用. 简单点说:外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便. 概述: 在真实的应用系统中,一个子系统可能由很多类组成.子系统的客户为了它们的需要,需要和子系统中的一些类进行交互.客户和子系统的类进行直接的交互会导致客户端对

[设计模式] 外观模式facade

外观模式应该是用的很多的一种模式,特别是当一个系统很复杂时,系统提供给客户的是一个简单的对外接口,而把里面复杂的结构都封装了起来.客户只需使用这些简单接口就能使用这个系统,而不需要关注内部复杂的结构.DP一书的定义:为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用.举个编译器的例子,假设编译一个程序需要经过四个步骤:词法分析.语法分析.中间代码生成.机器码生成.学过编译都知道,每一步都很复杂.对于编译器这个系统,就可以使用外观模式.可以定义

11.外观模式(Facade Pattern)

using System; namespace ConsoleApplication4 { class Program { /// <summary> /// 不使用外观模式的情况 /// 此时客户端与三个子系统都发送了耦合,使得客户端程序依赖与子系统 /// 为了解决这样的问题,我们可以使用外观模式来为所有子系统设计一个统一的接口 /// 客户端只需要调用外观类中的方法就可以了,简化了客户端的操作 /// 从而让客户和子系统之间避免了紧耦合 /// </summary> ///

java设计模式----外观模式

外观模式主要应用场景在于为复杂的子系统提供一个简单的接口,提高子系统的独立性. 创建DrawerOne类: package facade; public class DrawerOne { public void open() { System.out.println("第一个抽屉被打开了"); getKey(); } public void getKey() { System.out.println("得到第一个抽屉的钥匙"); } } 创建DrawerTwo类:

设计模式--外观模式Facade(结构型)

一.外观模式 外观模式提供了一个统一的接口,用来访问子系统中的一群接口.外观模式定义了一个高层接口,让子系统更容易被使用. 二.UML图 三.例子 举个编译器的例子,假设编译一个程序需要经过四个步骤:词法分析.语法分析.中间代码生成.机器码生成.学过编译都知道,每一步都很复杂.对于编译器这个系统,就可以使用外观模式.可以定义一个高层接口,比如名为Compiler的类,里面有一个名为Run的函数.客户只需调用这个函数就可以编译程序,至于Run函数内部的具体操作,客户无需知道. class Scan