【发布时间】:2020-03-23 09:18:28
【问题描述】:
对于我正在实施的特定状态模式,我不确定最佳 OO 设计方法应该是什么。请考虑以下几点:
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));
}
…
}
我犹豫的是这里new这个词的用法,即。用另一个状态实例化new SomeState(),或在Controller 或另一个State 内实例化new SomeRequest()。在我看来,这会在 State 和它们的兄弟姐妹以及 Controller 和 States 之间产生高度耦合。
要求如下:
- 必须可以添加新状态,例如添加
SniffingState。 -
还必须可以用新状态替换现有状态。例如,我应该能够将
OffLeachState替换为执行不同操作的不同OffLeashState。例如(由于某种原因代码不会格式化):公共类 OffLeachState2 扩展 DogState {
公共无效seeCat(猫猫){
if (dog.knows(cat)) {
// 狗变成“PlayWithCatState”
// cat 得到一个“PlayWithDog”请求
} 其他 {
// 狗变为“ChaseAnimalState”
}
}
} 最后,必须记录
World类中的所有更改。这意味着 World 类有一个记录器,可以跟踪正在发生的一切。这也是因为 World 类是一个模型,并且必须触发notifyObservers()以便视图知道要做什么。
我的问题是,状态、请求等应该存储在哪里?例如:
Dog中是否应该有状态“getter”?例如,dog.getBarkingState()、dog.getOnLeashState()等?这似乎是有道理的,但它不会使Dog类抗拒改变。即,每次我添加一个新的DogState类时,我还必须确保Dog有一个getter。此外,World不知道这些更改,因此它不会记录它们也不会通知观察者。是否应该有一个名为
DogStates的类并且我可以运行DogStates.getBarkingState()?再次,与上述类似的问题。他们应该成为
World类的一部分吗?例如,world.setDogState(dog, world.getDogBarkingState()?这将解决日志记录/更新问题,但会给World类带来太多责任。应该是它们的某种组合,例如
world.setState(dog, dog.getBarkingState()?这可能很好,但不能保证类型安全。例如,我可以将Dog对象与CatState一起传递,它不会知道区别。
解决方案 #4 对我来说似乎是最好的,但我想对这个问题提出一些其他意见。
同样的问题也适用于Request 对象。我最初想通过与对象关联的字符串发送Requests,例如world.sendRequest(dog, DogRequests.SEE_CAT),但后来我无法将cat对象作为参数传递。
非常感谢您的宝贵时间!
【问题讨论】:
标签: java design-patterns structure state-pattern