Cowboy Tech

iOS设计模式-适配器

视图在中央

cardView.center = self.view.center;

直接赋值的弊端

如果要修改的话,需要修改所有赋值(目前有三处)

ViewController

BusinessCardView *cardView = [[BusinessCardView alloc] initWithFrame:BUSINESS_FRAME];
cardView.name        = @"Hello";
cardView.lineColor   = [UIColor redColor];
cardView.phoneNumber = @"101 - 5687 - 000";

对象赋值(封装)

以一个类进行封装,降低了耦合度,只需要修改一处(model)。但问题是,如果导入的对象与loadData方法不一致呢?

BusinessCardView *cardView = [[BusinessCardView alloc] initWithFrame:BUSINESS_FRAME];

Model *model      = [[Model alloc] init];
model.name        = @"Hello";
model.lineColor   = [UIColor redColor];
model.phoneNumber = @"101 - 5687 - 000";

[cardView loadData:model];

使用适配器模式

  1. 创建抽象适配器对象
  2. 适配器与视图层建立输出联系
  3. 适配器与数据层建立输入联系
  4. 类适配器与对象适配器

Protocl + Adapter

BusinessCardAdapterProtocol

//输出的数据一致性
@protocol BusinessCardAdapterProtocol <NSObject>

- (NSString *)name;
- (UIColor *)lineColor;
- (NSString *)phoneNumber;

BusinessCardAdapter (空实现,用来让子类继承)

@interface BusinessCardAdapter : NSObject <BusinessCardAdapterProtocol>
@property (nonatomic, weak) id data;
- (instancetype)initWithData:(id)data;

@implementation BusinessCardAdapter
- (instancetype)initWithData:(id)data {
self = [super init];
if (self) {
    self.data = data;
}
return self;
}

- (NSString *)name {
return nil;
}

- (UIColor *)lineColor {
return nil;
}

- (NSString *)phoneNumber {
return nil;
}

BusinessCardView

//加载数据(实现了BusinessCardAdapterProtocol协议的数据)
- (void)loadData:(id <BusinessCardAdapterProtocol>)data {
self.name        = [data name];
self.lineColor   = [data lineColor];
self.phoneNumber = [data phoneNumber];
}

针对Model class 的类适配器

Model

@interface Model : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) UIColor  *lineColor;
@property (nonatomic, strong) NSString *phoneNumber;
@end

ModelAdapter(类适配器)

@interface ModelAdapter : BusinessCardAdapter

@end

@implementation ModelAdapter

- (instancetype)initWithData:(id)data {
self = [super init];
if (self) {        
    self.data = data;
}  
return self;
}

- (NSString *)name {  
Model *data = self.data; 
return data.name;
}

- (UIColor *)lineColor {
Model *data = self.data; 
return data.lineColor;
}

- (NSString *)phoneNumber {
Model *data = self.data;
return data.phoneNumber;
}

@end

ViewController

BusinessCardView *cardView = [[BusinessCardView alloc] initWithFrame:BUSINESS_FRAME];
Model *model      = [[Model alloc] init];
model.name        = @"JiKeXueYuan";
model.lineColor   = [UIColor redColor];
model.phoneNumber = @"101 - 5687 - 000";

// 与输入建立联系
BusinessCardAdapter *modelAdapter = [[ModalAdapter alloc] initWithData:model];

// 与输出建立联系
[cardView loadData:modelAdapter];

针对NewCardModel的类适配器

NewCardModel

@interface NewCardModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *colorHexString;
@property (nonatomic, strong) NSString *phoneNumber;
@end

NewCardModelApater (类适配器)

@interface NewCardModelApater : BusinessCardAdapter

@end

@implementation NewCardModelApater

- (instancetype)initWithData:(id)data {
self = [super init];
if (self) {
    self.data = data;
}
return self;
}

- (NSString *)name {
NewCardModel *data = self.data;
return data.name;
}

- (UIColor *)lineColor {
NewCardModel *data = self.data;
// todo
if ([data.colorHexString isEqualToString:@"black"]) {
    return [UIColor blackColor];
} else {
    return [UIColor redColor];
}
}

- (NSString *)phoneNumber {
NewCardModel *data = self.data;
return data.phoneNumber;
}
@end

ViewController

BusinessCardView *cardView = [[BusinessCardView alloc] initWithFrame:BUSINESS_FRAME];

NewCardModel *newCardModel  = [[NewCardModel alloc] init];
newCardModel.name           = @"JiKeXueYuan";
newCardModel.colorHexString = @"black";
newCardModel.phoneNumber    = @"101 - 5687 - 000";

// 与输入建立联系
BusinessCardAdapter *modelAdapter = [[NewCardModelApater alloc] initWithData:NewCardModel];

// 与输出建立联系
[cardView loadData:modelAdapter];

对象适配器(万能)

一个适配器解决所有数据模型,代码里会显得很臃肿

@interface CardAdapter : BusinessCardAdapter

@end

#import "CardAdapter.h"
#import "Model.h"
#import "NewCardModel.h"

@implementation CardAdapter

- (instancetype)initWithData:(id)data {
self = [super init];
if (self) {      
    self.data = data;
} 
return self;
}

- (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;
}

- (UIColor *)lineColor {
UIColor *lineColor = nil;
if ([self.data isMemberOfClass:[Model class]]) { 
    Model *model = self.data;
    lineColor    = model.lineColor; 
} else if ([self.data isMemberOfClass:[NewCardModel class]]) {
    NewCardModel *model = self.data;
    if ([model.colorHexString isEqualToString:@"black"]) {
        lineColor = [UIColor blackColor];  
    } else { 
        lineColor = [UIColor redColor];
    }
}
return lineColor;
}

- (NSString *)phoneNumber {
NSString *phoneNumber = nil;
if ([self.data isMemberOfClass:[Model class]]) {
    Model *model = self.data;
    phoneNumber  = model.phoneNumber;
} else if ([self.data isMemberOfClass:[NewCardModel class]]) {
    NewCardModel *model = self.data;
    phoneNumber         = model.phoneNumber;
}
return phoneNumber;
}
@end

适配器的优点和缺点

  1. 降低视图层和数据层的耦合度
  2. 让一个类在不经过修改的情况下适应更多的情形
  3. 代码可读性差,比较繁琐