[英]Strategy pattern in Objective-C
我写了一个示例代码策略设计模式。
@protocol MyProtocol
- (void)execute1;
@end
@interface BaseClass : NSObject
@property(nonatomic, assign) NSInteger commonValue;
- (void)commonCalculator;
@end
@interface DogClass : BaseClass <MyProtocol>
@end
@interface CatClass : BaseClass <MyProtocol>
@end
另外,我想创建一个 BaseClass 来实现一个通用逻辑。
但是,无法从 MyProtocol 类型访问 BaseClass。
例如
- (void)foo {
NSInteger type = 0;
id<MyProtocol> obj = [self simpleFactory:type];
[obj execute1]; // It works!!
// I'd like the following code. However compile error occurs.
[obj commonCalculator]; // error
obj.commonValue = 10; // error
// I don't want the following code.
if (type == 0 ) {
[(DogClass *)obj commonCalculator];
((DogClass *)obj).commonValue = 10;
} else {
[(CatClass *)obj commonCalculator];
((CatClass *)obj).commonValue = 10;
}
}
- (id<MyProtocol>)simpleFactory:(NSInteger)type {
if (type == 0) {
return [[DogClass alloc] init];
} else {
return [[CatClass alloc] init];
}
}
有没有办法在使用策略模式时在 BaseClass 中使用通用代码?
如果BaseClass
实现了<MyProtocol>
默认行为,那么BaseClass
应该采用并实现<MyProtocol>
。
@interface BaseClass : NSObject <MyProtocol>
@property(nonatomic, assign) NSInteger commonValue;
- (void)commonCalculator;
@end
然后子类将继承该协议:
@interface DogClass : BaseClass
...
@interface CatClass : BaseClass
...
好消息是子类可以调用[super execute1]
并且如果您尝试使用或传递BaseClass
的实例作为id<MyProtocol>
编译器不会抱怨。
现在,如果出于某种无法解释的原因,您必须将BaseClass <MyProtocol>
的超类实现的代码分离到它自己的模块中,则可以通过创建一个采用并实现您的默认实现的BaseClass
类别来做到这一点:
@interface BaseClass (MyProtocolDefaults) <MyProtocol>
@end
...
@implementation BaseClass (MyProtocolDefaults)
- (void)execute1
{
...
}
@end
如果你这样做,我仍然建议你仍然不要在你的子类中重新采用协议(即使它是完全合法的),而是通过导入BaseClass
类别来“选择”协议:
#import "BaseClass.h"
#import "BaseClass+MyProtocolDefaults.h"
@interface DogClass : BaseClass
// this class adopts <MyProtocol> indirectly through the BaseClass category
就我理解的正确而言,我将尝试解释:
1)我同意您宁愿将基类订阅到您的协议,而不是订阅每个孩子。 2)如果您要通过协议使用多态性,您应该携带:
- (void)commonCalculator;
方法到协议,而不是基类。 然后你将能够在需要的地方实现所需的逻辑,比如在基类中。 只需在那里实现这个方法。
3)另外我想给一个建议:Apple工程师喜欢使用Class Cluster模式,这是工厂模式的一个特例。 因此,在 .h 文件中,您将拥有如下内容:
@protocol MyProtocol<NSObject>
@property (assign, nonatomic, readonly) NSInteger commonValue;
- (void)commonCalculator;
- (void)execute;
@end
typedef NS_ENUM(NSUInteger, BaseClassType) {
BaseClassTypeA,
BaseClassTypeB,
BaseClassTypeC
};
@interface BaseClass: NSObject<MyProtocol>
- (instancetype)initWithType:(BaseClassType)type;
@end
@interface SubclassA: BaseClass
@end
@interface SubclassB: BaseClass
@end
@interface SubclassC: BaseClass
@end
通过你的代码,你将只使用基类的实例,但在引擎盖下它将是具体子类的实例。 因此,您的 .m 文件的实现将如下所示:
@implementation BaseClass
- (instancetype)initWithType:(BaseClassType)type {
switch (type) {
case BaseClassTypeA: {
self = [[SubclassA alloc] init];
}
case BaseClassTypeB: {
self = [[SubclassB alloc] init];
}
case BaseClassTypeC: {
self = [[SubclassC alloc] init];
}
}
return self;
}
@end
如您所见,这说明了如何使用策略模式的示例,(因为就是这样,我们有几种策略,并且相对于实例化的策略将执行所需的方法,因此,每个策略都在引擎盖下封装了一些算法,但它隐藏在公共接口后面)与类集群模式(这是工厂模式的特殊情况)相结合。 您应该记住,只要它与您的应用程序设计和谐地集成,您将在策略协议中引入多少方法并没有任何严格的标准。 这种方法使您的应用程序设计非常优雅且易于理解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.