ios设计原则-迪米特法则

906 阅读3分钟

迪米特法则(最少知道原则)

  • 一个对象应该对尽可能少的对象有接触,也就是只接触那些真正需要接触的对象。
  • 迪米特法则也叫做最少知道原则(Least Know Principle), 一个类应该只和它的成员变量,方法的输入,返回参数中的类作交流,而不应该引入其他的类(间接交流)。

优点

  • 实践迪米特法则可以良好地降低类与类之间的耦合,减少类与类之间的关联程度,让类与类之间的协作更加直接。

类比需求

  • 设计一个汽车类,包含汽车轮胎的品牌名字,提供一个方法返回汽车轮胎名称。

不好的设计

16205680402825.jpg

-------- car.h ---------
@interface Car : NSObject

- (instancetype)init;

- (Tyre *)getTyre;

@end

-------- car.m ---------

#import "Car.h"
#import "Tyre.h"
@interface Car ()
@property(nonatomic,strong)Tyre *tyre;
@end

@implementation Car
- (instancetype)init{
    self = [super init];
    if (self) {
        Tyre *tyre = [[Tyre alloc]init];
        tyre.tyreName = @"米其林轮胎";
        self.tyre = tyre;
    }
    return self;
}

- (Tyre *)getTyre{
    return _tyre;
}

  • car的基本构造方法,重写init方法,并创建了一个轮胎实例并设置轮胎名字为"米其林",同时car类对外提供了一个返回轮胎实例的方法getTyre.

  • 轮胎类中tyre有一个轮胎名字的成员变量tyreName

------- Tyre.h --------
@interface Tyre : NSObject
@property(nonatomic,copy)NSString *tyreName;
@end
  • 在测试控制器中获取轮胎名字
#import "Car.h"
#import "Tyre.h"


-------- ViewController ------
- (void)viewDidLoad {
    [super viewDidLoad];
    
    Car *car = [[Car alloc]init];
    NSString *tyreName = [self getTheCarTyreName0:car];
    NSLog(@"%@",tyreName);
    
}
- (NSString *)getTheCarTyreName0:(Car *)car{
    Tyre *tyre = [car getTyre];
    NSString *tyreName = tyre.tyreName;
    return tyreName;
}
  • 上面的设计虽然完成了需求,但是违反了迪米特法则,在控制器中 getTheCarTyreName0:中多引入了一个Tyre对象。增加了控制器和Tyre的耦合。而这个耦合是可以避免的。加入都是这样的设计,加入汽车的很多的其他对象都要再次与控制器耦合显然不利于代码的维护和拓展。

好的设计

16205682256045.jpg

  • 同样是Car,我们直接返回轮胎的名字的方法,取消了返回轮胎对象的方法。
----- Car.h ------
@interface Car : NSObject

- (instancetype)init;

- (NSString *)getTyreName;

@end


------- Car.m ------
#import "Car.h"
#import "Tyre.h"
@interface Car ()
@property(nonatomic,strong)Tyre *tyre;
@end

@implementation Car
- (instancetype)init{
    self = [super init];
    if (self) {
        Tyre *tyre = [[Tyre alloc]init];
        tyre.tyreName = @"米其林轮胎";
        self.tyre = tyre;
    }
    return self;
}

- (NSString *)getTyreName{
    return _tyre.tyreName;
}

@end
  • 因为直接返回了轮胎名字,所以在控制器就可以直接拿到这个值,不是通过中间tyre实例对象来获取。控制器也不必引入Tyre的头文件。
------ ViewController -----
#import "ViewController.h"
#import "Car.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Car *car = [[Car alloc]init];
    NSString *tyreName = [self getTheCarTyreName0:car];
    NSLog(@"%@",tyreName);
    
}

- (NSString *)getTheCarTyreName1:(Car *)car{
    return [car getTyreName];
}

@end

总结

  • 这样的好处是,如果我们还想获取这辆车的其他的属性名字时,控制器不用需要修改大量代码,也不用引入其他的类,直接通过Car类来获取,返回对应的名字就可以了。
  • 思考:
    • 今后在做对象与对象之间的交互设计时,应该尽量避免引入中间对象的情况,需要什么对象直接返回,降低类之间的耦合度。