设计模式【六】:适配器模式【接口适配】

设计模式【6】:适配器模式【接口适配】

objective-c中使用实施适配器模式的时候使用的是协议

适配器模式(Adapter Pattern),适配器模式又叫做变压器模式,也叫做包装模式(Wrapper),但是包装模式却不止一个,装饰模式也是包装模式。适配器模式是一种补救模式,他可以让你从因业务扩展而系统无法迅速适应的苦恼中解脱出来。我们在进行系统开发时,不管之前的可行性分析、需求分析、系统设计处理的多么完美,总会在关键时候、关键场合出现一些“意外”。这些“意外”,该来的还是要来,躲是躲不过的,而这时就是我们的适配器模式的用武之地。适配器模式最好在设计阶段不要考虑它,它不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,没有一个系统分析师会再做详细设计时考虑使用适配器模式

适配器模式包含两种,一种是类适配器,另一种是对象适配器类适配器是通过类的继承实现的适配,而对象适配器是通过对象间的关联关系,组合关系实现的适配。二者在实际项目中都会经常用到,由于对象适配器是通过类间的关联关系进行耦合的,因此在设计时就可以做到比较灵活,而类适配器就只能通过覆写源角色的方法进行拓展,在实际项目中,对象适配器使用到的场景相对较多。在iOS开发中也推荐多使用组合关系,而尽量减少继承关系,这是一种很好的编程习惯,因此我在这里只介绍对象适配器,想了解更多的关于类适配器的话,请自行Google之。

适配器模式的官方定义:

将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式优点

  1. 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。
  2. 增加了类的透明性。我们访问的是目标角色,但是实现却在源角色里。
  3. 提高了类的复用度。源角色在原有系统中还是可以正常使用的。
  4. 灵活性非常好。不想要适配器时,删掉这个适配器就好了,其他代码不用改。

适配器模式的objective-C实现

Target
1
2
3
4
5
6
7
#import <Foundation/Foundation.h>

@protocol Target <NSObject>

- (void)userExpectInterface;

@end
Adaptee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import <Foundation/Foundation.h>

@interface Adaptee : NSObject

- (void)doSometing;

@end

@implementation Adaptee

- (void)doSometing
{
    NSLog(@"adaptee doing something!");
}

@end
Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#import "Target.h"
#import "Adaptee.h"

@interface Adapter : NSObject<Target>

@property (strong, nonatomic) Adaptee *adaptee;

- (id)initWithAdaptee:(Adaptee *)adaptee;

@end

@implementation Adapter

@synthesize adaptee = _adaptee;


- (id)initWithAdaptee:(Adaptee *)adaptee
{
    if (self = [super init]) {
        _adaptee = adaptee;
    }
    return self;
}

- (void)userExpectInterface
{
    [self.adaptee doSometing];
}

@end
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <Foundation/Foundation.h>
#import "Adapter.h"
#import "Adaptee.h"
#import "Target.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Adaptee *adaptee = [[Adaptee alloc]init];
        id<Target> object = [[Adapter alloc]initWithAdaptee:adaptee];

        [object userExpectInterface];

    }
    return 0;
}