如何避免在状态设计模式中进行类型转换或对象 class 检查?

How to avoid typecasting or object class checking in state design pattern?

我正在实施状态管理器来控制对象状态模式。我的 StateManager 有一个属性 currentMode,可以是 PenStateEraserStateZoomState 类型(State 的所有子类)。

但是,在接收方获取 currentMode 时,如何避免类型转换?设计有什么问题?正确的做法是什么?

State *state = [StateManager sharedManager].currentMode;
if([state isKindOfClass:[PenState Class]]) //how to avoid this type checking
{
    penState *penState = (PenState*)state;
    CGSize penSize = penState.size;
}

我的课程

@interface PenState : State

@property(nonatomic,strong) NSString *color;
@property(nonatomic,assign) CGSize size;

@end

@interface StateManager : NSObject
{

}
@property(nonatomic,strong)State *currentMode;

@end

更新:

我是否需要在 State Class 中维护枚举

    typedef NS_ENUM(NSInteger, Mode)
    {
        None = 0,
        Pen,
        Eraser,
        Zoom
    };

@protocol StateProtocol <NSObject>
-(Mode)toolbarMode;
@end

@implementation WriteState

-(Mode)toolbarMode
{
    return Pen;
}

@end

状态模式的要点是,从状态机的角度来看,状态应该是可互换的,因此每个状态都应该符合一个协议(或者在你的情况下,一个 superclass 应该present the common interface)它提供了所有的共同需求。因此,你所有的状态(你的工具)都应该接受一个大小和一个使用指定大小的动作,要么设置笔的大小并画一条线,要么设置缩放大小并执行缩放。

如果状态存在差异,您可以进行 class 检查,这应该相对不常见并且在相对特定的代码中。如果代码是特定的,那么您通常应该知道预期的 class,这样您就可以进行类型转换。

继承和协议也可用于创建状态的子集,因此您可以拥有工具状态(具有大小),也可以具有绘图状态(具有颜色),然后您可以继续类型转换为super class / 协议而不关心每个具体的实现 class.