依赖倒置原则
- 定义
- 1.上层模块不应该依赖底层模块,他们都应该依赖于抽象
- 2.抽象不应该依赖于细节,细节应该依赖于抽象
- 3.高层模块不能依赖底层模块,两者都应该依赖抽象
- 4.业务层处于上层模块,逻辑层和数据层为底层
- 优点
- 通过抽象来搭建框架,建立类和类的关联,以减少类间的耦合性。而且以抽象搭建的系统要比以具体实现搭建的系统更加稳定,扩展性更高,同时也便于维护。
- 通过代码具体例子讲解
- 需求时一家披萨店,能生产各类品种的披萨
- 整理底层和高层,披萨店自然就是高层,披萨为低层。从逻辑思考惯性出发
- pizzaStore 依赖所有的Pizza对象,因为他能够创建披萨对象
- pizza 有很多种
- 如芝士披萨
- 素食披萨
- 海鲜披萨
- 等等
不好的设计
- 没有依赖抽象而是具体依赖具体,pizza店依赖具体的pizza类
- 创建枚举根据枚举创建爱你具体的pizza类
typedef enum : NSUInteger {
PizzaTypeOne,
PizzaTypeTwo,
PizzaTypeThree,
} PizzaType;
@interface PizzaStore : NSObject
- (NSObject *)creatPizzaWithType:(PizzaType)type;
- 根据枚举值的不同分别调用了他们具体创建方法
@implementation PizzaStore
- (NSObject *)creatPizzaWithType:(PizzaType)type{
if (type == PizzaTypeOne) {
return [PizzaOne makePizzaOne];
}
if (type == PizzaTypeTwo) {
return [PizzaTwo makePizzaTwo];
}
if (type == PizzaTypeThree) {
return [PizzaThree makePizzaThree];
}
return nil;
}
@end
- 缺点就是当这个需求不断变多时pizza的种类不断变多时他们特有的不同的构造方法时,你也需要在店铺类中调用,注意不要调错方法了。
-
依赖倒置:
- 我们从底层开始想上思考,很多的披萨种类,多种多样的创建方法能不能使用同一种方法然后在子类中重写自己的方法。所以我们就构想出了一个pizza类。一个抽象类,然后又一个构造的抽象方法,再往上推设计店铺
#import "PizzaNew.h" NS_ASSUME_NONNULL_BEGIN typedef enum : NSUInteger { PizzaTypeNewOne, PizzaTypeNewTwo, PizzaTypeNewThree, } PizzaNewType; @interface PizzaNewStore : NSObject - (PizzaNew *)creatPizzaWithNewType:(PizzaNewType)type;- (PizzaNew *)creatPizzaWithNewType:(PizzaNewType)type{ if (type == PizzaTypeNewOne) { return [PizzaNewOne makePizza]; } if (type == PizzaTypeNewTwo) { return [PizzaNewTwo makePizza]; } if (type == PizzaTypeNewThree) { return [PizzaNewThree makePizza]; } return nil; }-
通过观察我觉得没什么差别呀,还不是一样的枚举创建不一样的子类吗。
-
注意的一点是新的构建方法多了一个抽象类,这个能帮助我们提高代码的灵活性和拓展性
-
1.添加属性方面我们可以在抽象类中添加,子类属性继承父类。
-
@property(nonatomic,assign)BOOL KK; //用来判断pizza是否为新品。在构造方法中默认设置为NO。
-
当我们构造了新的pizza子类时可以重新构造方法设置新的子类KK属性为Yes,表示这个披萨是新品。而不用在每个披萨类中添加自己的属性
-
也可以利用这个抽象类,将pizza的基本属性全都写上去
-
如果子类有自己特有的属性时可以在子类中添加,这样有符合了开闭原则了
-
- 如何实践 今后在处理高低层模块(类)交互的情景时,尽量将二者的依赖通过抽象的方式解除掉,实现方式可以是通过接口也可以是抽象类的方式。