我被指派设计一个软件(在 Java 中),其中包含项目和作业,其中每个作业都有一个状态。当我们了解到 GoF-patterns ,State 模式对我来说似乎是一个显而易见的选择,但现在我在实现时遇到了一些麻烦。
在我目前的设计中,我有一个 Job
-class 表示具有特定状态和 Project
的作业- 具有作业列表的类。为了表示四种可能的状态( AVAILABLE
- UNAVAILABLE
- FINISHED
- FAILED
),我做了一个枚举 State
在枚举中实现与状态相关的作业方法。
我遇到的状态模式问题如下:
- 在
Project
, 我想要一个返回所有AVAILABLE
的方法项目的工作(甚至可能返回所有FINISHED
或FAILED
的工作),但状态模式没有提及如何执行此操作。我们还听说有方法作为public boolean isAvailable()
在Job
或State
在使用状态模式时不应使用(因为这正是使用此模式时想要避免的情况)。 - 需要一种方法来改变
AVAILABLE
的状态工作FINISHED
或FAILED
.问题是我不太确定在使用状态模式时如何实现它。
我有一些解决方案,但我想知道是否有其他/更好的解决方案可以很好地实现状态模式。
- 对于第一个问题,我会实现一个
public Collection<Job> filter(Collection<Job>)
State
中的方法这将返回给定集合的子集,其中仅包含当前状态的那些作业。getAvailableJobs()
Project
中的方法会像下面这样。这种方法对我来说的缺点是当Project
时耦合会增加。需要了解State
- 对于第二个问题,我可以写一个
update(State newState)
我可以检查的方法newState
要么完成要么失败,或者我可以写一个方法fail()
和一种方法finish()
(当然都在State
中)。第二个问题似乎是一些状态逻辑在Job
中返回的事实。 , 但我不确定update
是否方法也是最好的方法。
我希望我已经足够清楚了,希望有人能帮助我理解为什么这些解决方案足够好或不好,以及可能的替代方案是什么。
提前致谢。
一些额外的代码让更多的事情变得清晰:
public class Project {
private final Set<Job> jobs;
// constructors, getters, setters, ...
// for updating, I need to be able to present only the available tasks
public Collection<Job> getAvailableJobs() {
return Status.AVAILABLE.filter(getJobs());
}
}
public class Job {
private final State state;
// Constructors, getters, setters, ...
// update either to finished or failed
// (Timespan is nothing more than a pair of times)
public void update(Timespan span, State newState) {
getState().update(this, span, newState);
}
}
public enum State {
AVAILABLE {
@Override
public void update(Job job, Timespan span, State newState) {
if(newState == AVAILABLE || newState == UNAVAILABLE)
throw new IllegalArgumentException();
job.setSpan(span);
job.setState(newState);
}
},
UNAVAILABLE, FINISHED, FAILED;
public void update(Job job, State newState) {
throw new IllegalStateException();
}
public Collection<Job> filter(Collection<Job> jobs) {
Collection<Job> result = new HashSet<>();
for(Job j : jobs)
if(j.getStatus() == this)
result.add(j);
return result;
}
}
最佳答案
@问题 1: 只要只有一个项目必须过滤其作业,过滤方法就应该是 Project
类的一部分。您可以提供一种按给定状态和具体状态进行过滤的通用方法(如果经常使用,为什么不将其作为 API 的一部分):
class Project {
private Set<Job> jobs;
public Set<Job> filterJobs(JobState state) {
return jobs.stream().filter(j -> j.getState() == state).collect(Collectors.toSet());
}
public Set<Job> availableJobs() {
return filterJobs(JobState.AVAILABLE);
}
}
两者都工作正常并且对用户透明:
project.availableJobs();
project.filterJobs(JobState.<your state>);
@问题2:还在想“有多少状态”在里面。根据描述,只有 AVAILABLE (2) 的状态转换,并且只有一种方法与之相关。根据我的经验和理解,如果有必要,应该应用设计模式,而不是从头开始。你的解决方案就这样很好。但是考虑到这里描述的几个要求,如果没有状态模式,它可能会简单得多。 (= YAGNI )
关于java - 使用状态模式获取具有特定状态的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30039351/