Java 使用状态模式解耦状态
对于我正在实现的特定状态模式,我不确定最好的OO设计方法应该是什么。请考虑以下事项:Java 使用状态模式解耦状态,java,design-patterns,structure,state-pattern,Java,Design Patterns,Structure,State Pattern,对于我正在实现的特定状态模式,我不确定最好的OO设计方法应该是什么。请考虑以下事项: public class World { private Animal dog_; private Animals cats_; ….. public void sendDogRequest(DogRequest request) { dog_.sendRequest(request); } … public Cat getCat(Stri
public class World {
private Animal dog_;
private Animals cats_;
…..
public void sendDogRequest(DogRequest request) {
dog_.sendRequest(request);
}
…
public Cat getCat(String catName) {
…
return cat;
}
...
}
public class Animal<RequestType extends Request, StateType extends State> {
private State<StateType> currentState_;
….
public void sendRequest(RequestType request) {
request.sendToState(currentState_);
}
public void setState(StateType state) {
currentState_ = state;
}
}
public class Dog extends Animal<DogState> {
…
}
public class DogState extends State {
public DogState(Dog dog) {
…
}
public void seeCat(Cat cat) { }
}
public class OnLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new BarkingState());
}
}
public class OffLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new ChasingAfterAnimalState(cat));
cat.sendRequest(new RunAwayRequest(cat));
}
}
public interface Request<StateType extends State> {
public void sendToState(StateType state);
}
public class DogRequest extends Request<DogState> { }
public class SeeCatRequest extends DogRequest {
private Cat cat_;
public SeeCatRequest(Cat cat) {
cat_ = cat;
}
public void sendToState(DogState state) {
state.seeCat(state);
}
}
public class Controller() {
public Controller(World model, View view) {
…
}
...
public void catSelected(String catName) {
Cat cat = world.getCat(catName);
Dog dog = world.getDog();
world.sendDogRequest(new SeeCatRequest(cat));
}
…
}
公共类世界{
私人动物狗;
私人动物猫;
…..
公共无效sendDogRequest(DogRequest请求){
狗发送请求(请求);
}
…
公共猫getCat(字符串catName){
…
返回猫;
}
...
}
公营动物{
私有状态当前状态;
….
公共无效发送请求(请求类型请求){
请求。发送状态(当前状态);
}
公共无效设置状态(StateType状态){
当前状态=状态;
}
}
公家犬{
…
}
公共类DogState扩展了状态{
公共狗州(狗){
…
}
公共无效seeCat(Cat){}
}
仅限公共类状态扩展DogState{
公共无效seeCat(Cat){
dog.setState(新的BarkingState());
}
}
fleashstate的公共类扩展了DogState{
公共无效seeCat(Cat){
狗状态(动物状态(cat)之后的新分类);
cat.sendRequest(新的RunAwayRequest(cat));
}
}
公共接口请求{
public void sendToState(StateType状态);
}
公共类DogRequest扩展请求{}
公共类SeeCatRequest扩展了DogRequest{
私家猫;
公共搜索请求(Cat){
猫=猫;
}
公共无效sendToState(DogState状态){
state.seeCat(state);
}
}
公共类控制器(){
公共控制器(世界模型、视图){
…
}
...
已选择公共无效catName(字符串catName){
Cat=world.getCat(catName);
Dog Dog=world.getDog();
sendDogRequest(新SeeCatRequest(cat));
}
…
}
我犹豫不决的地方是这里的单词new
的用法,即用另一个状态实例化new SomeState()
,或Controller
或另一个状态中的new SomeRequest()
。在我看来,这将在状态和它们的兄弟之间产生高度耦合,以及控制器
和状态
s
要求如下:
必须能够添加新状态,例如添加SniffingState
还必须能够用新的国家取代现有的国家。例如,我应该能够将OffLeachState
替换为执行不同操作的不同OffLeashState
。例如(由于某些原因,代码无法格式化):
LeachState2的公共类扩展了DogState{
公共空间见Cat(Cat){
如果(狗知道(猫)){
//狗变为“玩猫状态”
//cat收到“PlayWithDog”请求
}否则{
//狗变为“追逐动物状态”
}
}
}
最后,必须记录世界
类中的所有更改。这意味着世界级的记录器可以跟踪正在发生的一切。这也是因为世界级是一个模型,必须触发一个notifyobservators()
,以便视图知道要做什么
我的问题是,状态、请求等应该存储在哪里?例如:
Dog
中是否应该有状态“getter”?例如,dog.getBarkingState()
,dog.getOnLeashState()
,等等?这似乎是有道理的,但它并不能使Dog
类抵制更改。也就是说,每次我添加一个新的DogState
类时,我还必须确保Dog
有一个getter。而且,World
不知道这些更改,因此它不会记录这些更改,也不会通知观察者
是否应该有一个名为DogStates
的类,我可以运行DogStates.getBarkingState()
?同样,与上述问题类似
他们应该成为世界的一部分吗?例如,world.setDogState(dog,world.getDogBarkingState()
?这将解决日志记录/更新问题,但将太多的责任放在world
类上
是否应该是它们的某种组合,例如world.setState(dog,dog.getBarkingState()
?这可能很好,但不能保证类型安全。例如,我可以将dog
对象与CatState
传递,它不会知道区别
解决方案4对我来说似乎是最好的,但我想听听关于这个问题的其他意见
同样的问题也适用于Request
对象。我最初希望通过与对象关联的字符串发送Request
s,例如world.sendRequest(dog,DogRequests.SEE_CAT)
,但是我无法将CAT对象作为参数传递
非常感谢您抽出时间!1。)这看起来像是一个编程考试题。在这种情况下,如果不确定要做什么,请使用模式!因此每个状态都应由StateFactory生成,并向Factory实例提供一些有关世界的信息,以便它可以决定创建哪个特定的状态实例
以下是日志记录:
public class World implements StateChangeListener {
private Animal dog_;
private Animals cats_;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
public World() {
listeners.add(this);
}
// Instead of sending DogRequests to Dogs via the sendDogRequest method:
public <RequestType extends Request> void sendRequest(
Animal<RequestType, ?> animal, Request<RequestType> request) {
animal.sendRequest(request);
for(StateChangeListener listener : listeners) {
listener.stateChanged(animal, request);
}
}
public void stateChanged(Animal<?, ?> animal, State<?> state) {
// ... log here ...
}
...
公共类世界实现StateChangeListener{
私人动物狗;
私人动物猫;
私有最终列表侦听器=新的ArrayList();
公共世界(){
添加(这个);
}
//不要通过sendDogRequest方法向狗发送狗请求:
公共无效发送请求(
动物(动物,请求){
动物。发送请求(请求);
for(StateChangeListener:侦听器){
状态改变(动物,请求);
}
}
公共无效状态已更改(动物,状态){
//…在这里登录。。。
}
...
还有工厂里的东西
public enum LocationEnum {
HOME, PARK, POND, FOREST
}
public interface StateFactory<StateType extends State> {
State<StateType> create(Animal<StateType, ?> animal, Context context);
}
// Do stuff Dogs do.
public class DogStateFactory<DogState> {
public State<DogState> create(Animal<DogState, ?>, Context context) {
if(context.currentAnimalLocation==LocationEnum.POND) {
return new IgnoreEverythingState();
}else if(context.currentAnimalLocation==LocationEnum.HOME){
return new PerpetualBarkState();
}else {
return new FollowEveryCatState();
}
}
}
public class Animal<RequestType extends Request, StateType extends State> {
private StateFactory<StateType> stateFactory;
private State<StateType> currentState_;
public void sendRequest(Request<RequestType> request) {
request.sendToState(currentState_);
}
// A specific animal knows what it wants to do, depending on it's current
// state and it's situational context. We don't want other animals
// to set the state for us.
public void determineState() {
currentState_ = stateFactory.create(this, new Context(...));
// One might want to extend the messaging stuff in a way that
// the World instance can log this state change.
}
}
public class Dog extends Animal<DogRequest, DogState> {
public Dog() {
this.stateFactory = new DogStateFactory<DogState>();
}
}