Java 如何强制只有应用程序中的给定模块才能更改对象中的属性?

Java 如何强制只有应用程序中的给定模块才能更改对象中的属性?,java,design-patterns,Java,Design Patterns,我有一个具有状态属性的类。实例化时,此属性包含对象的当前状态。这些状态有一个定义良好的流(例如:从状态1只能转到状态2和状态3。从状态2只能转到状态4等等),因此我打算在我的系统中创建一个模块来管理这些更改。 理想情况下,它将接收对象和执行的操作,并设置新状态。 我知道如何做到这一点,但我忽略了一点:如何强制每个人使用此模块来更改状态?我不想任何人改变状态,只想改变这个模块 是否有一个设计模式或OO“技巧”我可以使用 我不知道这是否有用,但我使用的是JAVA EE6。您只需对mutator/se

我有一个具有状态属性的类。实例化时,此属性包含对象的当前状态。这些状态有一个定义良好的流(例如:从状态1只能转到状态2和状态3。从状态2只能转到状态4等等),因此我打算在我的系统中创建一个模块来管理这些更改。 理想情况下,它将接收对象和执行的操作,并设置新状态。 我知道如何做到这一点,但我忽略了一点:如何强制每个人使用此模块来更改状态?我不想任何人改变状态,只想改变这个模块

是否有一个设计模式或OO“技巧”我可以使用


我不知道这是否有用,但我使用的是JAVA EE6。

您只需对mutator/setter使用包访问可见性,并将要保护的实例与模块中可以更改它的类放在同一个包中

例如:

package com.bla.bla.bla.models;
public class ProtectedData {
    private String protectedField;
    public String getProtectedField() {
        return protectedField;
    }
    void setProtectedField(String newValue) {//package visibility
        this.protectedField = newValue;
    }
}

package com.bla.bla.bla.models;//the same package (no matter the name)
public class ProtectedWorkflowController {

    public void closeProtectedData(ProtectedData data) {
        data.setProtectedField(null);
    }
}

PS:模块的概念在爪哇中是<代码>未定义< /代码>,所以我认为在您的情况下考虑Mult= =包是没有错的。

我的头顶:

 class A {

   protected State state

   public State getState(){ return state; }
 }

 class B extends A {

   public void setState( State s ){ this.state = s }

 }
因此,对于类A的所有用户,该属性仍然是只读的,但如果将实例强制转换为B,则该属性是可写的

更新:

要使用回调机制,请执行以下操作:

 interface StateChanger(){ 
    public void call( State state );
 }

 class A {

   protected State state

   public State getState(){ return state; }

   public void setState( StateChanger stateChanger ){
     stateChanger.call( state );
   }
 }
然后您可以将其用作:

 classAInstance.setState( new StateChanger(){
    @Override
    public void call( State state ){
      //do stuff
    }
 } );
也许您需要在
StateChanger.call()
中也包含
this
作为参数


在Groovy这样的动态语言中,它看起来非常紧凑

对不起,我不能这样做,因为我想在其中存储有关状态更改的所有知识的模块在概念上不是一个子类。我这样做是因为流很复杂,我想封装它。您还可以使用(内部匿名)回调类来设置
state
属性的新值。这将限制以“政治”方式写入您的财产听起来很有趣,但我不知道怎么做,我将对此进行研究,感谢您为我指出这个解决方案:)在我的原始帖子中添加了一些行。我会将这一行标记为答案,因为在与我的团队进行了大量阅读和讨论后,我们了解到我们的方向是错误的:实体应该调用服务并更新自己的状态,而不是更新实体的服务。这个答案引起了我们的讨论(顺便说一句:谢谢!:)听起来不错。我的类当前位于com.bla.bla.bla.models包中,而我的系统位于另一个包中。要使它工作,我必须使它们都在同一个包中,并且是这个包中仅有的两个类。这是正确的吗?没错:)我加了一个例子。该包中还可以有多个类,只需确保该模块中没有其他类(我希望您可以控制它,并且没有人会有从该包的其他类操纵它的坏主意)。它看起来不错,我将向我的团队推荐:)