Java设计模式-外观模式

外观模式(Facade)提供了一种统一访问子系统的方法,降低了客户端与子系统间的耦合。本文通过一个数学老师收集作业的例子,详细解释了外观模式的原理、组成和优缺点,并展示了其实现代码。外观模式使得子系统的修改对客户端无影响,增强了系统的可维护性和可扩展性。
摘要由CSDN通过智能技术生成

一、简介

1.1 引入

在寒假结束以后,开学第一天,数学老师进门说:“你们把寒假作业交上来”,每个人独自来我办公室交作业。于是,同学陆续前往办公室交作业,一下子,办公室被围得水泄不通。
在这里插入图片描述
语文老师听说了数学老师的"事迹",让语文课代表把所有同学的寒假作业收齐以后,统一送到语文老师的办公室。
在这里插入图片描述
我们能够看到,语文老师办法显然更加方便。如果有哪位同学没有交齐作业,只需要让课代表记录一下,这样就可以减轻老师的工作量了。

语文老师的办法和接下来我们要了解的外观模式很类似,接下来就让我们一起去了解一下什么是外观模式吧。

1.2 定义

外观(Facade)模式:外观模式又叫门面模式,它为多个复杂的子系统提供一个一致的接口,这个接口使得这些子系统更容易被使用

  • 该模式对外有一个"统一的接口",外界可以通过这个接口访问子系统,而不用直接访问子系统
  • 外部应用程序在访问子系统时,不用关心内部子系统的具体细节,大大降低了应用程序的复杂度,提高了程序的可维护性。

二、模式原理

2.1 模式组成

组成(角色)作用
Facade(外观)Facade是一个类,该类包含了子系统中全部或部分类的实例引用。当用户要和子系统打交道时,可以通过和Facade外观类来和子系统打交道
Subsystem(子系统)子系统可以有一个或多个,每个子系统可以不是一个单独的类,而是若干个类的集合,这些类的实例协同合作为用户提供所需要的功能,子系统并不知道外观类的存在,所以子系统中的任何一个类都不包含对外观类的实例引用。

2.2 UML类图

在这里插入图片描述

三、实例

3.1 实例概况

  • 概括:数学老师学习了语文老师的办法,让语文课代表收集班级同学的寒假作业(这里假设班级人数3人)
  • 利用外观模式帮助数学老师收集作业,并输出每位同学作业完成情况

3.2 步骤

  • 步骤一:创建外观类,并且包含所有子系统的实例引用,可自己组合相关的方法
//外观类,包含了所有子系统的实例引用
public class MathRep {
	public LiHua liHua;
	public Tom tom;
	public Jerry jerry;

	// 因为子系统中的getInstance()都是静态的,所以可以直接用类名调用
	public MathRep() {
		liHua = LiHua.getInstance();
		tom = Tom.getInstance();
		jerry = Jerry.getInstance();
	}

	// 提交作业,调用所有子系统的实例,用户只需要直接调用 外观角色 即可,无需自己创建子系统实例
	public void submit() {
		liHua.submit();
		tom.submit();
		jerry.submit();
	}

	public void condition() {
		liHua.condition();
		tom.condition();
		jerry.condition();
	}
}
  • 步骤二:创建子系统,各个子系统互相独立,使用单例模式-饿汉式创建实例
//子系统,聚合到外观类中
public class LiHua {

	// 单例模式,饿汉式
	private static LiHua liHua = new LiHua();

	public static LiHua getInstance() {
		return liHua;
	}

	// 作业提交
	public void submit() {
		System.out.println("李华提交数学作业");
	}

	// 作业完成情况
	public void condition() {
		System.out.println("李华完成情况100%,well done");
	}
}
//子系统,聚合到外观类中
public class Tom {

	// 单例模式,饿汉式
	private static Tom tom = new Tom();

	public static Tom getInstance() {
		return tom;
	}

	// 作业提交
	public void submit() {
		System.out.println("汤姆提交数学作业");
	}

	// 作业完成情况
	public void condition() {
		System.out.println("汤姆完成情况80%,Do ok");
	}
}
//子系统,聚合到外观类中
public class Jerry {
	// 单例模式,饿汉式
	private static Jerry jerry = new Jerry();

	public static Jerry getInstance() {
		return jerry;
	}

	// 作业提交
	public void submit() {
		System.out.println("杰瑞提交数学作业");
	}

	// 作业完成情况
	public void condition() {
		System.out.println("杰瑞完成情况59%,don't pass");
	}
}
  • 步骤三:用户通过外观类实现相关功能,不用和子系统直接接触
public class MathTeacher {
	public static void main(String[] args) {

		// 用户不需要和子系统打交道,只需要直接和外观类打交道即可
		// 创建一个数学课代表,由课代表收作业,反映作业完成情况
		MathRep mathrep = new MathRep();

		mathrep.submit();
		System.out.println("----------");
		mathrep.condition();
	}
}
//执行结果
李华提交数学作业
汤姆提交数学作业
杰瑞提交数学作业
----------
李华完成情况100%,well done
汤姆完成情况80%,Do ok
杰瑞完成情况59%,don't pass

3.3 UML类图

在这里插入图片描述

四、优缺点

4.1 优点

  • 使客户端和子系统中的类无耦合,使得子系统使用起来更加方便
  • 一个子系统的修改对其他子系统没有任何影响,而且子系统中任何类对其方法进行修改,并不影响外观类的代码
  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类
  • 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统

4.2 缺点

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

五、应用场景

  • 对于一个复杂的子系统,需要为用户提供一个简单接口时。并且该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统
  • 不希望客户端和子系统之间存在耦合,可以使用外观模式让客户端和子系统解耦,以便提高子系统的独立性和可移植性
  • 当整个系统需要构建一个层次结构的子系统,不希望这些子系统相互直接的交互时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值