[设计模式]外观模式

 

外观模式(Facade)在开发过程中的运用频率非常高,尤其是在现阶段各大种第三方SDK充斥在我们的周边,而这些SDK很大概率会使用外观模式。通过一个外观类使得整个系统的接口只有一个统一的高层接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节。当然,在我们的开发过程中,外观模式也是我们封装API的常用手段,例如网络模块、ImageLoader模块等。

 

定义

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式(Facade模式)提供一个高层次的接口,使得子系统更易于使用。

 

使用场景

1.为一个复杂子系统提供一个简单接口。子系统往往因为不断深化而变得越来越复杂,甚至可能被替换。大多数模式使用时都会产生更多、更小的类,在这使子系统更具可重用性的同时也更容易对子系统进行定制、修改,这种易变性使得隐藏子系统的具体实现变得尤为重要。Facade可以提供一个简单统一的接口,对外隐藏子系统的具体实现、隔离变化;

2.当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过Facade接口进行通信,从而简化了它们之间的依赖关系。

 

UML类图

Facade:系统对外的统一接口,系统内部系统地工作。

SubSystemOne.... : 子系统接口。

外观模式接口比较简单,就是通过一个统一的接口对外提供服务,使得外部程序只通过一个类就可以实现系统内部的多种功能,而这些实现功能的内部子系统之间可能也有交互,或者说完成一个功能需要几个子系统之间进行协作,如果没有封装,那么用户就需要操作几个子系统的交互逻辑,容易出现错误。而通过外观类来对外屏蔽这些复杂的交互,降低用户的使用成本。

 

示例

拿手机为例,它集合了电话、相机等等多种功能,通过手机你就可以完成各种功能,而不是你打电话时用一个老爷机,拍照时拿出个相机,如果是这样每使用一个功能你就必须操作特定的设备,会使得整个过程很繁琐,手机就相当于整合了各个子系统的外观模式。

 

public class MobilePhone {
	private Phone phone = new PhoneImpl();
	private Camera camera = new SamsungCamera();
	
	public void dail(){
		phone.dail();
	}
	
	public void videoChat(){
		System.out.println("---->视频聊天连接中");
		camera.open();
		phone.dail();
	}
	
	public void hangup(){
		phone.hangup();
	}
	
	public void takePicture(){
		camera.open();
	}
	
	public void closeCamera(){
		camera.close();
	}
	
	/**
	 * MobliePhone类中含有两个子系统,拨号系统与拍照系统,MobliePhone将这两个系统封装起来,为用户提供一个统一的操作接口,也就是说用户只需要通过MobilePhone这个类就可以操作打电话和拍照
	 * 这两个功能,用户不需要知道有Phone这个接口以及它的实现类是PhoneImpl,同样也不需要知道Camera相关的信息,通过MobilePhone就可以包揽一切。而在MobilePhone中也封装了两个子系统的
	 * 交互,例如视频电话时需要先打开摄像头,然后再开始拨号,如果没有这一步的封装,每次用户实现视频通话功能时都需要手动打开摄像头,进行拨号,这样会增加用户的使用成本,外观模式使得这些操作更加简单。
	 */
}
public interface Phone {
	//打电话
	public void dail();
	
	//挂断
	public void hangup();
}
public class PhoneImpl implements Phone{

	@Override
	public void dail() {
		System.out.println("打电话");
	}

	@Override
	public void hangup() {
		System.out.println("挂断");
	}

}
public interface Camera {
	public void open();
	public void takePicture();
	public void close();
}
public class SamsungCamera implements Camera{

	@Override
	public void open() {
		System.out.println("打开相机");
	}

	@Override
	public void takePicture() {
		System.out.println("拍照");
	}

	@Override
	public void close() {
		System.out.println("关闭相机");
	}

}
public class Client {
	public static void main(String[] args) {
		MobilePhone iphone = new MobilePhone();
		iphone.takePicture();
		iphone.videoChat();
	}
	
	//运行结果:
		/*打开相机
		---->视频聊天连接中
		打开相机
		打电话*/
}

从代码中可以看到,外观模式就是统一接口封装。将子系统的逻辑、交互隐藏起来,为用户提供一个高层次的接口,使得系统更加易用,同时也对外隐藏了具体的实现,这样即使具体的子系统发生了变化,用户也不会感知到,因为用户使用的是Facade高层接口,内部的变化对于用户来说并不可见。这样一来就将变化隔离开来,使得系统也更为灵活。

 

 

总结

外观模式是一个高频率使用的设计模式,它的精髓就在于封装二字,通过一个高层次结构为用户提供统一的API入口,使得用户通过一个类型就基本能够操作整个系统,这样减少了用户的使用成本,也能够提升系统的灵活性。

优点

1.对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化。

2.外观类对子系统的接口封装,使得系统更易于使用。

缺点

1.外观类接口膨胀,由于子系统的接口都有外观类统一对外暴露,使得外观类的API接口较多,在一定程度上增加了用户使用成本。

2.外观类没有遵循武闭原则,当业务出现变更时,可能需要修改外观类。







 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

peak wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值