结构型模式之外观模式

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

上面介绍了半天定义没明白对吧?下面简单来说
外观模式通过引入一个外观角色来简化客户端和子系统之间的交互,为复杂的子系统调用提供一个统一的接口,降低子系统和客户端的耦合度,而客户端调用非常方便

举个例子说明吧
不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶、茶具和开水,如图所示,而去茶馆喝茶,最简单的方式就是跟茶馆服务员说想要一杯什么样的茶,是铁观音、碧螺春还是西湖龙井?正因为茶馆有服务员,顾客无须直接和茶叶、茶具、开水等交互,整个泡茶过程由服务员来完成,顾客只需与服务员交互即可,整个过程非常简单省事,如图所示。
在这里插入图片描述
在软件开发中,有时候为了完成一项较为复杂的功能,一个客户类需要和多个业务类交互,而这些需要交互的业务类经常会作为一个整体出现,由于涉及到的类比较多,导致使用时代码较为复杂,此时,特别需要一个类似服务员一样的角色,由它来负责和多个业务类进行交互,而客户类只需与该类交互.外观模式通过引入一个新的外观类(Facade)来实现该功能,外观类充当了软件系统中的“服务员”,它为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。

模式结构和说明

外观模式

Facade:定义子系统的多个模块对外的高层接口.通常需要调用内部多个模块,从而把客户的请求代理给适当的子系统对象
模块:接受Facade对象的委派,真正实现功能,各个模块之间可能有交互.但是请注意,Facade对象知道各个模块,但是各个模块不应该知道Facade对象。

示例代码

  1. 定义各个模块的接口,对外提供各自的功能方法,下面我定义了三个模块AModule,BModule,CModule
@implementation AModule

- (void)testA
{
    NSLog(@"test A ");
}

@end
@implementation BModule

- (void)testB
{
    NSLog(@"test B ");
}
@end
@implementation CModule

- (void)testC
{
    NSLog(@"test C ");
}
@end
  1. 定义外观对象,代码如下
@implementation Facade

- (void)test
{
    AModule *a = [AModule new];
    [a testA];
    BModule *b = [BModule new];
    [b testB];
    CModule *c = [CModule new];
    [c testC];
}
@end
  1. 客户端使用
   Facade *facade = [Facade new];
    [facade test];
  1. 结果
    在这里插入图片描述
    从上面的例子看出,Facade类相当于A,B,C模块的外观界面,Facade类也被称为A,B,C模块对外的接口,有了这个Facade类,那么客户端就不需要知道系统内部的实现细节,甚至客户端都不需要知道A,B,C模块的存在,客户端只需要跟Facade类交互就好了,从而更好的实现了客户端和子系统中A、B、C模块的解耦,让客户端更容易的使用系统。

模式讲解

目的

外观模式的目的不是给子系统添加新的功能接口,而是为了让外部减少与子系统内多个模块的交互,松散耦合,从而让外部能够更简单的使用子系统。

使用外观跟不使用相比有何变化

看了上面的示例,很多人会有疑惑,Facade模式不就把客户端的代码移到Facade了吗?相当于再封装了一下,没什么变化啊?

没错,表面上看就是把客户端的代码搬到Facade里面了,但实质是发生了变化的,请思考:Facade到底位于何处呢?是位于客户端还是在由A、B、C模块组成的系统这边呢?

答案肯定是在系统这边,这有什么不一样吗?

当然有了,如果Facade在系统这边,那么它就相当于屏蔽了外部客户端和系统内部模块的交互,从而把A、B、C模块组合成为一个整体对外,不但方便了客户端的调用,而且封装了系统内部的细节功能,也就是说Facade与各个模块交互的过程已经是内部实现了。这样一来,如果今后调用模块的算法发生了变化,比如变化成要先调用B,然后调用A,那么只需要修改Facade的实现就可以了。

另外一个好处,Facade的功能可以被很多个客户端调用,也就是说Facade可以实现功能的共享,也就是实现复用。同样的调用代码就只用在Facade里面写一次就好了,而不用在多个调用的地方重复写。

优点

  1. 降低了客户类与子系统类的耦合度,实现了子系统与客户之间的松耦合关系
  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类
  • 减少了与子系统的关联对象,实现了子系统与客户之间
    的松耦合关系,松耦合使得子系统的组件变化不会影响到它的客户。
  1. 外观模式对客户屏蔽了子系统组件,从而简化了接口,减少了客户处理的对象数目并使子系统的使用更加简单
  • 引入外观角色之后,用户只需要与外观角色交互;
  • 用户与子系统之间的复杂逻辑关系由外观角色来实现
  1. 降低原有系统的复杂度和系统中的编译依赖性,并简化了系统在不同平台之间的移植过程

因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。

缺点

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

Demo地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值