设计模式之——外观模式

1.概述

       外观模式(Facade Pattern)隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

        举个现实生活中的例子:在大陆去大型医院看病

        下面用一个示意图来表示这个过程:

        

实现上面这种流程的简易代码实现: 

package cn.xnn;

/**
    * 类(接口)描述:挂号类
 * @author xnn
 * 2018年11月25日下午9:48:48
 */
public class Register {
public void Regist() {
	System.out.println("挂号成功");
}
}


package cn.xnn;

/**
    * 类(接口)描述:门诊类
 * @author xnn
 * 2018年11月25日下午9:51:29
 */
public class OutpatientService {
public void Diagnosis() {
	System.out.println("医生开始诊断了");
}
}


package cn.xnn;

/**
 * 类(接口)描述:化验类
 * @author xnn
 * 2018年11月25日下午10:20:55
 */
public class Test {
	public void test() {
		System.out.println("去化验");
	}
}


package cn.xnn;

/**
    *  类(接口)描述:划价类
 * @author xnn
 * 2018年11月25日下午9:53:10
 */
public class Pricing {
public void pay() {
	System.out.println("诊断完毕,开始划价缴费");
}
}


package cn.xnn;

/**
    * 类(接口)描述:抓药类
 * @author xnn
 * 2018年11月25日下午9:54:24
 */
public class Prescription {
public void fetch () {
	System.out.println("划价缴费完毕,可以抓药了");
}
}


package cn.xnn;

/**
 * 类(接口)描述:患者类
 * @author xnn
 * 2018年11月25日下午9:55:48
 */
public class Patient {
	private static Register register =new Register();
	private static OutpatientService outpatientService=new OutpatientService();
	private static Prescription prescription=new Prescription();
	private static Pricing pricing=new Pricing();
	private static Test test = new Test();
public static void main(String[] args) {
	//挂号
	register.Regist();
	//去门诊看病
	outpatientService.Diagnosis();
	//化验
	test.test();
	//划价缴费
	pricing.pay();
    //取药
	prescription.fetch();
}
}

        类图结构:

        从系统图中可以看到,病人看病需要挂号、门诊诊断、化验、划价、取药等过程,并且所有的这些过程都需要患者(客户端)去亲力亲为访问医院这个系统(软件系统)。显然,从图上就可以感觉到,相互间调用太麻烦,耦合性也很大;

        从类图中也可以感觉到,patient这个类引用的对象太多了,即客户端和系统内部接触太多,耦合太大。

      解决这种不便的一个方式就是引入外观(门面)模式,具体设计如下(还是以上面的医院系统为例):

在其中间加一个接待员(即后面要说的门面类)的角色,这样整个系统看起来就没有那么乱了。

代码体现(在上面的基础上引入一个接待员类,并且客户端类也要做一些改动):

package cn.xnn;

/**
 * 类(接口)描述:接待员类
 * @author xnn
 * 2018年11月25日下午10:09:10
 */
public class Receptionist {
	private  Register register;
	private  OutpatientService outpatientService;
	private  Prescription prescription;
	private  Pricing pricing;
	private Test test;
	/**
	 * 在构造门面类时   创建这些相关的组件  ( 相当于把这些引用放到门面类中去,而不是让客户端直接引用)
	 */
	public Receptionist() {
		 register = new Register();
		 outpatientService=new OutpatientService();
		 prescription=new Prescription();
		 pricing=new Pricing();
		 test = new Test();
	}
	
	//看小病
	public void DiagnosisLightIllness() {
		//挂号
		register.Regist();
		//划价缴费
		pricing.pay();
		//取药
		prescription.fetch();
	}
	    //看大病
		public void DiagnosisCriticallyIllness() {
			//问诊
			register.Regist();
			//化验
			test.test();
			//划价缴费
			pricing.pay();
			//取药
			prescription.fetch();
		}
}


package cn.xnn;

/**
 * 类(接口)描述:
 * @author xnn
 * 2018年11月25日下午10:27:39
 */
public class NewPatient {
	//引入门面类
	 private static Receptionist receptionist =new Receptionist();

public static void main(String[] args) {
	 //看小病
	 receptionist.DiagnosisLightIllness();
	 System.out.println("----------------");
	 //看大病
	 receptionist.DiagnosisCriticallyIllness();
}
}

类图:

 

从改动后的代码看,客户端只需要引入一个门面类对象的引用即可,减少耦合,并且客户端代码量也减少很多。

2、模式中的角色

3、模式的优缺点

优点:

       1、减少系统相互依赖;

       2、符合迪米特法则(客户端只“认识”门面类就好)

       3、提高灵活性;

       4、提高了安全性

缺点:

     不符合开闭原则(对扩展开放,对修改关闭。即系统若想增加一些功能,则我们可以通过扩展的方式,去实现这些想要的功能,而不必去修改原有的代码。),若系统运行一段时间后,发现功能不全,需要增加一个子系统去实现另外的一个功能,这个时候,你不仅需新增一个子系统的代码(对扩展开放,符合开闭原则。)但若想还甩这个门面模式的话,就不得不修改门面角色这个类(违背了对修改关闭这一原则);但是可以通过引入抽象外观类在一定程度上解决该问题,假若系统中又增加了一个新的子系统,我们可以在起初设计的时候就先写一个抽象外观类,然后写该抽象类的另一个具体实现类,把新的子系统功能封装进去。就上面的系统来说,若又增加了个报销子系统,我就可以再增加抽象外观类的子类,把报销的功能加进去,这样就符合了开——闭原则了。

4、模式的应用场景

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值