我正在尝试创建使用枚举来指定状态的状态计算机。由于有很多状态,并且每个州实现的逻辑非常复杂,因此我想将每个状态与将在其他类中定义的状态处理程序相关联。每个状态处理程序将实现一个通用的接口(或扩展一个常见的摘要类(,但是每个界面可能都有其其他可能不需要的注入依赖项。到目前为止,这样的东西....
StateHandler接口:
public interface StateHandler {
void onActivation();
void onDeactivation();
}
示例状态人:
@Singleton
public class DefaultStateHandler implements StateHandler {
@Inject
public DefaultStateHandler(SomeDependency someDependency) {...}
/** implement onActivation, onDeactivation and state specific logic **/
}
@Singleton
public class OtherStateHandler implements StateHandler {
@Inject
public OtherStateHandler(SomeOtherDependency someOtherDependency) {...}
/** implement onActivation, onDeactivation and state specific logic **/
}
StateManager实施:
@Singleton
public class StateManager {
private StateType stateType = StateType.DEFAULT;
@Inject
public StateManager() { }
public void changeState(StateType newStateType) {
if (stateType != newStateType) {
stateType.getStateHandler().onDeactivation();
stateType = newStateType;
stateType.getStateHandler().onActivation();
}
}
}
枚举定义:
public enum StateType {
DEFAULT (/* not sure what to do here */),
OTHER_STATE (...);
private StateHandler stateHandlerInstance;
public getStateHandler { return stateHandlerInstance; }
StateType(/* not sure what to do here */) {
/* assign stateHandlerInstance */
}
}
我要弄清楚的是...在声明其相关枚举时,如何注入状态处理者的特定实例?或者,如果不可能,是否有另一种方式来指定每个枚举的状态处理程序类,然后(在构造函数中或第一个需要时(,获取关联的状态处理程序实例?
<?我最初认为我需要将州的处理程序实例注入状态枚举定义。但是,由于注射需要公共建筑商和枚举使用私人构造函数,因此我认为这种方法是可行的。
如上所述,解决方案是使用MAP多键。
首先简化了枚举刻板:
public enum StateType {
DEFAULT, OTHER_STATE
}
现在我们需要特定于此枚举类型的daggermapkey接口:
@MapKey
@interface StateTypeKey {
StateType value();
}
接下来,我们需要一个dagger模块,该模块将为每个刻板类型/stateHandler组合具有提供商功能:
@Module
public StateTypeHandlersModule {
// @Provides @IntoMap // Syntax for dagger >= 2.9
@Provides(type = Provides.Type.MAP) // Syntax for dagger <= 2.8
@StateTypeKey(StateType.DEFAULT)
StateHandler provideDefaultStateHandler(DefaultStateHandler handler) {
return handler;
}
// @Provides @IntoMap // Syntax for dagger >= 2.9
@Provides(type = Provides.Type.MAP) // Syntax for dagger <= 2.8
@StateTypeKey(StateType.OTHER_STATE)
StateHandler provideOtherStateHandler(OtherStateHandler handler) {
return handler;
}
}
不幸的是,这是很多样板代码,这就是为什么我仅将单独的模块用于处理程序,并且在高级状态机器模块中包括该模块。请注意,如果您声明两个提供商使用相同的stateTypeKey函数,则第二个处理程序最终可在注入的地图中可用。
最后,我们可以将Map<StateType, StateHandler>
注入stateManager:
@Singleton
public class StateManager {
private Map<StateType, StateHandler> stateHandlerMap;
private StateType stateType = StateType.DEFAULT;
@Inject
public StateManager(Map<StateType, StateHandler> stateHandlerMap) {
this.stateHandlerMap = stateHandlerMap;
}
public void changeState(StateType newStateType) {
if (stateType != newStateType) {
stateHandlerMap.get(stateType).onDeactivation();
stateType = newStateType;
stateHandlerMap.get(stateType).onActivation();
}
}
}