java - 使用状态模式获取具有特定状态的对象

标签 java design-patterns state-pattern

我被指派设计一个软件(在 Java 中),其中包含项目和作业,其中每个作业都有一个状态。当我们了解到 GoF-patterns ,State 模式对我来说似乎是一个显而易见的选择,但现在我在实现时遇到了一些麻烦。

在我目前的设计中,我有一个 Job -class 表示具有特定状态和 Project 的作业- 具有作业列表的类。为了表示四种可能的状态( AVAILABLE - UNAVAILABLE - FINISHED - FAILED ),我做了一个枚举 State在枚举中实现与状态相关的作业方法。

我遇到的状态模式问题如下:

  1. Project , 我想要一个返回所有 AVAILABLE 的方法项目的工作(甚至可能返回所有 FINISHEDFAILED 的工作),但状态模式没有提及如何执行此操作。我们还听说有方法作为 public boolean isAvailable()JobState在使用状态模式时不应使用(因为这正是使用此模式时想要避免的情况)。
  2. 需要一种方法来改变 AVAILABLE 的状态工作FINISHEDFAILED .问题是我不太确定在使用状态模式时如何实现它。

我有一些解决方案,但我想知道是否有其他/更好的解决方案可以很好地实现状态模式。

  1. 对于第一个问题,我会实现一个 public Collection<Job> filter(Collection<Job>) State 中的方法这将返回给定集合的子集,其中仅包含当前状态的那些作业。 getAvailableJobs() Project 中的方法会像下面这样。这种方法对我来说的缺点是当 Project 时耦合会增加。需要了解 State
  2. 对于第二个问题,我可以写一个 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/

相关文章:

java - 如何在应用程序中正确处理对文件的引用?

c++ - 在这种情况下,代理或状态设计模式或迭代器模式更合适吗?

c++ - 交互类 - 组织代码

java - java.util.Iterator 的实现是否使用状态模式?

c# - .NET - 可以将 DI 与状态模式一起使用吗?

java - 使用 POI 下载的文件已损坏,并且未存储弹出窗口中的数据

java - 从 .dat 文件加载对象

java - 自定义 UUID 作为主键

java - JSONAssert.assertEquals(objActual, jObject, true) 未按预期工作

asp.net - 本地化 .NET Web 应用程序的最佳方式(服务器端和客户端)