定义
高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖细节,细节应该依赖抽象
定义的理解
首先我们来看一下什么是高层模块,什么是低层模块:
- 高层模块:即调用一方
- 低层模块:即被调用的一方
不遵循依赖倒置原则
我们直接来看不遵循依赖倒置原则的写法,来进行理解,我先实现Person类
和Dog类
,然后Person类中有个feed方法,该方法会去调用Dog类中的eat方法
# Person类
--- Person.h
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person : NSObject
- (void)feed:(Dog *)instance;
@end
--- Person.m
#import "Person.h"
@implementation Person
- (void)feed:(Dog *)instance {
[instance eat];
}
@end
# Dog类
--- Dog.h
#import <Foundation/Foundation.h>
@interface Dog : NSObject
- (void)eat;
@end
--- Dog.m
#import "Dog.h"
@implementation Dog
- (void)eat {
NSLog(@"狗吃骨头");
}
@end
那在这部分实现的代码中,像Person类
就是高层模块,而Dog类
就是低层模块了,并且Person类
与Dog类
之间的关系是属于依赖关系,所以像这种写法就是反例,它违反了依赖倒置的原则
这种方式的写法虽然也能实现功能,但是当后续又有新的需求时,就需要修改高层模块的代码,比如说:我又需要实现Cat类
,Person也要去喂Cat,那这个时候原本的feed
方法就无法去实现喂Cat的功能,需要再专门写个方法来实现喂Cat的功能,代码如下:
--- Person.m
- (void)feedDog:(Dog *)instance {
[instance eat];
}
- (void)feedCat:(Cat *)instance {
[instance eat];
}
# Cat类
--- Cat.h
#import <Foundation/Foundation.h>
@interface Cat : NSObject
- (void)eat;
@end
--- Cat.m
#import "Cat.h"
@implementation Cat
- (void)eat {
NSLog(@"猫要吃鱼");
}
@end
那这个时候在main.m
中进行调用是没有问题的
--- main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
#import "Cat.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
Dog *d = [Dog new];
Cat *c = [Cat new];
[p feedDog:d];
[p feedCat:c];
}
return 0;
}
以上就是高层模块依赖于低层模块的写法,那接下来我们来看一下遵循了依赖倒置原则的写法
遵循依赖倒置原则
其实依赖倒置原则的核心思想就是面向接口编程,但是在OC中没有接口这个概念,这里我们可以使用协议作为替代。
0x001. 首先是实现一个Animal协议
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol Animal <NSObject>
@required
- (void)eat;
@end
NS_ASSUME_NONNULL_END
0x002. 然后让Dog类和Cat类都实现这个协议,并且将Person类中的feed方法也进行修改(这边Dog类和Cat类的代码就不贴出来了)
# Person类
--- Person.h
#import <Foundation/Foundation.h>
#import "Animal.h"
@interface Person : NSObject
- (void)feed:(id<Animal>)instance;
@end
--- Person.m
#import "Person.h"
@implementation Person
- (void)feed:(id<Animal>)instance {
[instance eat];
}
@end
0x003. 最后就是在main.m
中的调用
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
#import "Cat.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
Dog *d = [Dog new];
Cat *c = [Cat new];
[p feed:d];
[p feed:c];
}
return 0;
}
-------------------------------控制台输出-----------------------------
2021-12-10 09:31:34.519558+0800 依赖倒置原则[68479:1270575] 狗吃骨头
2021-12-10 09:31:34.520765+0800 依赖倒置原则[68479:1270575] 猫要吃鱼
以上就是遵循了依赖倒置原则的写法,通过多实现一层Animal协议
,使得高层模块(Person类)和低层模块(Dog类和Cat类)给隔离的出来,后续如果有新的需求时,就无需再修改高层模块的代码了
网友评论