文档章节

iOS设计模式-适配器

 刘星石
发布于 2016/04/12 16:26
字数 1607
阅读 14
收藏 0

原文出处: Lastdays(@Lastday_s)   

很好奇,什么是适配器,大家有没有听说过电源适配器,其实原理都是一样的,就是说我们的iPhone手机,在中国,可以用iPhone充电器给手机充电,都知道,中国的电压是220V,对吧,我们的iPhone额定输入电压是5V,其实这就是我们适配器的功劳,而且,我们的充电器在中国能用,当然如果我们去了美国,没过不是220V,难道我们的手机就不能充电了吗?当然肯定不会,总结来说:在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

 

为何使用适配器?

直接赋值的缺点

最简单明了就是直接写一个示例来说名

制作一张卡片:

对卡片的数据直接赋值:

Objective-C

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

#import "ViewController.h"

#import "BusinessCard.h"

 

@interface ViewController ()

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

 

    BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME];

    card.name = @"姓名";

    card.color = [UIColor blueColor];

    card.phoneNumber = @"电话";

 

    card.center = self.view.center;

 

    [self.view addSubview:card];

 

}

 

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}

 

@end

运行结果:

非常简单的一个示例,这基本上就是我们以前经常使用的一种方法直接赋值,这种的缺点,其实很简单,就是耦合性太强了,简简单单的移除更改,可能就会造成很多地方进行更改。现在看起来很简单就更改,但是如果我们的数据很多很多呢?

因此我们现在简单的来改进一下,设计一个model。并且在BusinessCard添加如下代码:

Objective-C

1

2

3

4

5

6

7

8

9

10

/**

*  初始化数据

*

*  @param model BusinessCard

*/

-(void)loadDataWithModel:(Model *)model{

    self.name        = model.name;

    self.phoneNumber = model.phoneNumber;

    self.line        = model.lineColor;

}

ViewController:

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

@interface ViewController ()

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib

    Model *model = [[Model alloc] initWithName:@"lastdays" phoneNumber:@"158******1111" lineColor:[UIColor blueColor]];

    BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME];

    card.center = self.view.center;

    [card loadDataWithModel:model];

    [self.view addSubview:card];

}

 

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}

@end

 

这样就降低了一些耦合性,这就是以对象形式赋值。

但是我们现在来阐述一个很致命的问题,那就是如果我们来了一个新的Model数据类型,其中的UIcolor是二进制形的。跟我们原来处理的数据类型不符合?这个时候怎么办?

其实解决方案很简单,这也就是上面提到过的,电源适配器原理。

使用适配器模型

电源有输入和输出,当然我们先来构建适配器

CardAdapterProtocol:

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

 

@protocol CardAdapterProtocol <NSObject>

 

- (NSString *)name;

 

- (UIColor *)lineColor;

 

- (NSString *)phoneNumber;

 

@end

CardAdapter:

Objective-C

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

31

32

33

34

35

36

37

38

39

40

41

#import <Foundation/Foundation.h>

#import "CardAdapterProtocol.h"

#import <UIKit/UIKit.h>

 

@interface CardAdapter : NSObject<CardAdapterProtocol>

 

/**

*  建立输入关系

*/

@property(nonatomic,weak) id data;

 

/**

*  与输入对象建立联系

*

*  @param data 输入的对象

*

*  @return 当前实例对象

*/

- (instancetype)initWithModel:(id)data;

 

@end

```

 

``` bash

#import "CardAdapter.h"

 

@implementation CardAdapter

 

- (NSString *)name{

    return nil;

}

 

- (UIColor *)lineColor{

    return nil;

}

 

- (NSString *)phoneNumber{

    return nil;

}

 

@end

 

这里我们构建了CardAdapterProtocol协议,以及抽象类CardAdapter,接下来就是创建ModelCardAdapter,这就是针对Model构建的适配器,然后覆盖内部方法进行重写。

这里需要做一下说明CardAdapter中通过initWithModel建立与Model的输入关系,就是我们在国内用充电器给手机充电,CardAdapter与Model的关系就是充电器跟220V电压的关系。

接下来就该建立充电器跟手机的关系了,这里面相当于构建CardAdapter和View的关系。

BusinessCard

Objective-C

1

2

3

4

5

6

7

8

9

10

/**

*  初始化卡片数据

*

*  @param model BusinessCard

*/

-(void)loadDataWithModel:(id<CardAdapterProtocol>)data{

    self.name        = [data name];

    self.phoneNumber = [data phoneNumber];

    self.line        = [data lineColor];

}

这样,我们基本上就完成了构建,测试:

ViewController:

Objective-C

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

31

32

33

#import "ViewController.h"

#import "BusinessCard.h"

#import "Model.h"

#import "ModelCardAdapter.h"

 

@interface ViewController ()

 

@end

 

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

 

    Model *model = [[Model alloc] initWithName:@"lastdays" phoneNumber:@"158******1111" lineColor:[UIColor blueColor]];

 

    //建立充电器跟电源关系

    CardAdapter *cardAdapter = [[ModelCardAdapter alloc] initWithModel:model];

 

    BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME];

    card.center = self.view.center;

 

    //建立手机跟充电器关系

    [card loadDataWithModel:cardAdapter];

    [self.view addSubview:card];

}

 

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

}

 

@end

测试结果:

以上我们使用的就是类适配器,当然还有一种叫做对象适配器,就是说无论我们是220V,还是100V,用这一个充电器都能给手机充电。这种如何实现?简单的说就是我们可以构建一个Adapter继承CardAdapter,简单的举个例子

Adapter

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (NSString *)name {

 

    NSString *name = nil;

 

    if ([self.data isMemberOfClass:[Model class]]) {

 

        Model *model = self.data;

        name         = model.name;

 

    } else if ([self.data isMemberOfClass:[NewCardModel class]]) {

 

        NewCardModel *model = self.data;

        name                = model.name;

 

    }

 

    return name;

}

根绝对象类型进行判断返回哪种处理结果。这种其实并不推荐,因为什么?因为现在的数据模型比较少,如果有10个,20个数据模型,那这个类到最好会非常的臃肿,并不方便我们维护。

总结

优点

优点显而易见,就是让适配器可以让我们的View更加强大,可以适配不同的数据,降低我们的耦合性

缺点

其实在代码中就可以看出来,一个简单赋值的东西,用了这么多东西,比较麻烦,有的时候是很繁琐的。但是呢?话又说回来,我们如果做了一个很牛的控件,为了提高它的通用性,加一个适配器会更好一些。 当我们的代码能力增加。但是呢? 这同样也是一个缺点,那就是代码的可读性不好。这点的权衡就靠自己来衡量,虽然麻烦一些,但是确实能够提高扩展性     QQ技术交流群290551701

本文转载自:http://ios.jobbole.com/84571/

共有 人打赏支持
粉丝 16
博文 142
码字总数 13945
作品 0
天津
私信 提问
如何判断你是合格的高级iOS开发工程师?

前言 随着移动互联网的高速发展泄洪而来,有意学习移动开发的人越来越多了,竞争也是越来越大,需要学习的东西很多。如何才能在激烈的移动开发者竞争中一枝独秀,成为一名真正合格的高级iOS...

_小迷糊
2018/05/26
0
0
移动开发之设计模式- 代理模式(IOS&Android)

资源 完全参照 代理模式|菜鸟教程但不包括IOS代码 代理模式 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有...

FlanneryZJ
2018/12/18
0
0
移动开发之设计模式-工厂模式(IOS&Android)

资源 完全参照 工厂模式|菜鸟教程 ,但不包括IOS代码 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳...

FlanneryZJ
2018/12/17
0
0
移动开发之设计模式- 命令模式(IOS&Android)

资源 完全参照 命令模式|菜鸟教程但不包括IOS代码 命令模式 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用...

FlanneryZJ
2018/12/19
0
0
移动开发之设计模式-适配器模式(IOS&Android)

资源 完全参照 组合模式|菜鸟教程 ,但不包括IOS代码 适配器模式 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口...

FlanneryZJ
2018/12/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux下find、awk、sed、grep命令的例子

find:搜索工具 # 列出当前目录及子目录下所有文件和文件夹find .# 在/home目录下查找以.txt结尾的文件名,-i表示忽略大小写find /home -iname "*.txt" find命令的详细介绍 awk:数据快...

吴伟祥
34分钟前
1
0
flink的Async I/O 异常处理

异常 Async function call has timed out1.3+AsyncFunctionflink-streaming-java_2.11-1.7.0-sources.jar!/org/apache/flink/streaming/api/functions/async/AsyncFunction.java@Public......

stys35
46分钟前
2
0
sql plus入门

用sqlplus操作数据库的基本步骤: #su - oracle $sqlplus / as sysdba >!ps -ef|grep ora #查看oracle进程,看看oracle是否已经启动,如果未启动则使用下面这条语句启动. >startup #启动oracl...

突突突酱
今天
1
0
kettle10 利用java代码解压gz格式文件

kettle默认只能解压zip格式的文件,比如linux里的tar、gz等格式的文件需要用到java代码来解压 在java代码里引入需要的包,要返回的变量 java代码如下 import java.io.BufferedInputStream;...

wells杨
今天
2
0
Wince之旅——设备控制(重启网卡为例)

其实根据我的实践,在wince下面重启网卡其实十分简单,直接把驱动程序和网卡分离然后再绑定一次就好了。怎么绑定呢。就是一个函数DeviceIoControl和底层通信下。 方法1 :把第二个参数设为I...

rainbowcode
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部