面试题答案
一键面试1. 遵循单一职责原则提高代码可维护性
假设我们要开发一个简单的 iOS 待办事项应用,有展示待办事项列表和添加待办事项功能。
- 不遵循单一职责原则的设计:
// 这个类试图处理展示和添加待办事项,职责不单一
@interface TodoManager : NSObject
- (void)displayTodos;
- (void)addTodo:(NSString *)todo;
@end
@implementation TodoManager
- (void)displayTodos {
// 展示待办事项逻辑
}
- (void)addTodo:(NSString *)todo {
// 添加待办事项逻辑
}
@end
这种设计下,如果展示逻辑或添加逻辑发生变化,可能会影响到另一个功能,可维护性较差。
- 遵循单一职责原则的设计:
// 负责展示待办事项列表
@interface TodoDisplay : NSObject
- (void)displayTodos;
@end
@implementation TodoDisplay
- (void)displayTodos {
// 展示待办事项逻辑
}
@end
// 负责添加待办事项
@interface TodoAdder : NSObject
- (void)addTodo:(NSString *)todo;
@end
@implementation TodoAdder
- (void)addTodo:(NSString *)todo {
// 添加待办事项逻辑
}
@end
这样,当展示逻辑改变时,只需要修改 TodoDisplay
类,添加逻辑改变时,只修改 TodoAdder
类,提高了代码的可维护性。
2. 在类的继承体系设计中避免违反开闭原则
开闭原则指软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
- 违反开闭原则的例子:
// 图形类
@interface Shape : NSObject
- (CGFloat)area;
@end
@implementation Shape
- (CGFloat)area {
return 0;
}
@end
// 圆形类继承自图形类
@interface Circle : Shape
@property (nonatomic, assign) CGFloat radius;
- (instancetype)initWithRadius:(CGFloat)radius;
@end
@implementation Circle
- (instancetype)initWithRadius:(CGFloat)radius {
self = [super init];
if (self) {
_radius = radius;
}
return self;
}
- (CGFloat)area {
return M_PI * self.radius * self.radius;
}
@end
// 假设现在要添加矩形类,如果在 Shape 类中直接修改添加新逻辑来处理矩形计算面积,就违反了开闭原则
@interface Rectangle : Shape
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end
@implementation Rectangle
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height {
self = [super init];
if (self) {
_width = width;
_height = height;
}
return self;
}
- (CGFloat)area {
return self.width * self.height;
}
@end
这里如果在 Shape
类中为了适应矩形添加新逻辑,就修改了 Shape
类,违反了开闭原则。
- 遵循开闭原则的做法:
// 图形类,定义抽象方法
@interface Shape : NSObject
- (CGFloat)area;
@end
@implementation Shape
- (CGFloat)area {
// 这里可以抛出异常或者做默认处理,实际应用中具体分析
@throw [NSException exceptionWithName:@"UnimplementedAreaCalculation" reason:@"Subclasses should implement area calculation" userInfo:nil];
}
@end
// 圆形类继承自图形类
@interface Circle : Shape
@property (nonatomic, assign) CGFloat radius;
- (instancetype)initWithRadius:(CGFloat)radius;
@end
@implementation Circle
- (instancetype)initWithRadius:(CGFloat)radius {
self = [super init];
if (self) {
_radius = radius;
}
return self;
}
- (CGFloat)area {
return M_PI * self.radius * self.radius;
}
@end
// 矩形类继承自图形类
@interface Rectangle : Shape
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end
@implementation Rectangle
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height {
self = [super init];
if (self) {
_width = width;
_height = height;
}
return self;
}
- (CGFloat)area {
return self.width * self.height;
}
@end
这种情况下,当添加新的图形类(如矩形)时,不需要修改 Shape
类,只需要扩展新的子类并实现相应的 area
方法,遵循了开闭原则。