做Joker的时候,遇到下面的设计问题。
不能传数量可变,类型可变的参数
状态机State有一个方法executeCommand,它接收外界发给State的Command,然后根据不同类型的Command来切换到下一个State,创建下一个State的时候,需要根据State的具体不同给State的构造函数传不同的参数。
正因为参数不一样,所以切换状态的代码不能弄成虚函数来搞多态。
这里也不能够由Command来实现具体的行为,因为具体行为由State来决定。所以只能是一大段的if else来判断Command类型,再在executeCommand里面实现具体的行为。但是在响应命令的时候,需要同时用到State对象的参数和Command传进来的参数,这样拿Command里面传过来的参数的时候就会有问题,如果是动态语言的话就可以随便传,但因为是静态语言,一个Command类不能传各种各样类型数量的参数。
这里有三种解决方法。
一种是建立多个Command的子类,不同子类携带不同的参数,然后在executeCommand里面根据Command的类型来给Command做强制类型转换。
另一种是实现一个可以传可变参数的类。让这个类实现getIntParam(const char *), getStringParam(const char *), getFloatParam(const char *) ... 这样的方法(当然这样的话这个传可变参数类支持的参数类型是有限的)。这样,对于一个类,就可以传不同的参数了。
第三种是用强大的模版来实现一个可以传任意数量任意类型参数的类,他实际上做了强制类型转换的工作,并且可以加入类型检查。
第一种方法简单,但是转错类型的话....
第二种复杂,但是可以在代码做检查,如果没有这个参数可以做错误记录。
第三种是现在的解决办法,非常好用。
不能将类型绑定到某个类或对象上
joker里面玩家和敌人的状态机有些状态一样,有些状态不一样。如果相同的状态如果都用同一个类表示,这样的画,这些相同状态在切换到下一个状态,而且这个状态的类型根据玩家和敌人是不一样的画,就会不知道该切换到哪个状态。例如当角色从静止状态切换到攻击状态的时候,如果不知道自己是玩家还是敌人,就不知道应该切换到玩家的攻击状态还是敌人的攻击状态。
当然比较恶心方便的做法是直接让状态机判断正在服务的角色对象究竟是玩家还是敌人。
但是对于更复杂的情况,比较好的做法应该是对象能够保存一个自己所用状态类的类列表,在切换状态的时候,直接取列表中的类来构造下一个状态对象。但是c++里面,是不能保存类作为数据的。
不过,可以在角色类里面加多一个字符串对应到创建状态类的工厂函数的unordered_map,这样状态机通过这个字典找到工厂函数来构造角色对应的状态。
网友评论