我写了一个示例代码策略设计模式。
@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中使用通用代码?
答案 0 :(得分:1)
如果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 :(得分:0)
据我所知,我将尝试解释:
1)我同意您宁愿将基类订阅到协议中,而不是订阅每个孩子。 2)如果要通过协议使用多态,则应携带:
- (void)commonCalculator;
方法适用于协议,而不适用于基类。然后,您将能够在所需的位置实现所需的逻辑,例如在基类中。只是在那里实现此方法。
3)我也想提一个建议: 苹果工程师喜欢使用类集群模式,这是工厂模式的特例。因此,在.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
如您所见,这说明了如何使用策略模式的示例,(因为它是,我们有几种策略,并且相对于实例化一种策略,将执行所需的方法,因此,每种策略都封装了某种算法在幕后,但它隐藏在通用接口后面)与类集群模式(这是Factory模式的特殊情况)结合使用。您应该记住,对于与战略协议和谐地集成到您的应用程序设计中的策略协议,没有严格的标准。 这种方法使您的应用程序设计非常优美且易于理解。