在设计应用程序时除了考虑设计模式之外,也需要考虑一些程序设计原则——构建可复用、可维护的面向对象应用程序。在iOS程序设计中主要考虑的设计原则是:
- 针对接口编程而不是针对实现编程
- 优先使用对象组合而不是类继承
一.针对接口编程
接口定义类型,接口继承让我们可以用一个对象代替另一个对象。具体来说就是实现相同接口的对象间可以相互替换。
接口继承在iOS开发中具体来说就是@protocol协议,一组协议就是一组接口,实现相同协议的对象间可以替换。下面一段代码定义了一个名为MyProtocol的协议
@protocol MyProtocol <NSOject>
@required
-(void)requiredMethod
@optional
-(void)optionalMethod
@end
协议定义的是类与类间的合约,因此使用协议必定涉及到两个类,一个类拥有协议,另一个类实现协议。
拥有协议的类
拥有协议的类知道协议有哪些接口,并且在特定的时候调用接口。具体如下:
@interface MyViewController:UIViewController
//通过属性的方式拥有协议,只要将某个遵守协议的对象赋值给delegate
//该对象内的协议接口实现就可以在MyViewController中调用了
@property (nonatomic,retain) id<MyProtocol> *delegate;
-(void)doProtocolFuntion;
@end
@implementation MyViewController
-(void)doProtocolFuntion{
[self.delegate requiredMethod];
[selg.delegate optionalMethod];
}
@end
实现协议的类
实现协议的类继承接口并实现接口。这样当有两个对象同时继承并实现协议接口是就可以很方便的实现前面说的对象替换。
@implementation AClass <MyProtocol>
-(void)requiredMethod{
NSLog(@"在AClass中实现requiredMethod");
}
-(void)optionalMethod{
NSLog(@"AClass实现optionalMethod");
}
@end
@implementation BClass <MyProtocol>
-(void)requiredMethod{
NSLog(@"在BClass实现requiredMethod");
}
-(void)optionalMethod{
NSLog(@"BClass实现optionalMethod");
}
@end
光是实现了协议接口还不能让MyViewController使用协议,还必须将MyViewController的delegate设置为相应的类
AClass *aClass = [[AClass alloc] init];
MyViewController *vc = [[MyViewController alloc] init];
vc.delelgate = aClass;
这样在执行
[vc doProtocolFuntion];
是就会调用AClass中定义的协议接口。同理,如果执行
BClass *bCLass = [[BClass alloc] init];
vc.delegate = bClass;
[vc doProtocolFuntion];
则会调用BClass中的协议接口实现,这就是接口对象替换。
二.使用对象组合
类继承可以使用其他的类来定义类的实现(如,类为抽象类则通过子类来实现其方法)。类继承通常被称为白箱复用(white-box reuse),因为父类的内部描述与细节子类都知道。
对象组合可以替代类继承,它通常被称为黑箱复用(black-box reuse),因为对象内部细节其他对象不可见。
使用对象组合的优点:
- 不会破坏封装:类继承中子类了解父类的细节,破坏了封装,而对象组合却不会
- 减少实现的依赖关系:类继承中子类的部分实现在父类中,相互依赖,而对象组合是接口定义实现
对象复用是我们在写iOS界面中经常用到的,只是我们平时没有注意而已。其实任意一个我们可间的界面都是多个对象复用而来的。下图是用Reveal看到的一个简单界面。
通过图片我们可以很明显的看到它是有多个对象组合而来的。
优先使用对象组合而不是类继承,并不是说完全不使用类继承。而是说在具体编程中根据情况,尽量使用对象组合。
比方说如果你已经有一个类来实现了图片展示功能
这时候,如果你要增加用户评论功能
这时应该优先考虑组合一个专门用来做评论的类,而不是继承这个图片展示类,然后再增加评论功能。