繁体   English   中英

限制不可变对象Java中的可变对象

[英]Restrict mutable object inside immutable object Java

我正在学习不可变的对象。 我正在尝试这段代码

  public final class ImmutableObject {

    private final String name;

    private final NormalObject obj =  new NormalObject();

    public String getName() {
        return name;
    }


    public ImmutableObject(String name) {
        this.name = name;
        obj.setName(name);
    }


    public NormalObject getObj() {

        NormalObject tempObj = obj;
        return tempObj;
    }
}

public class NormalObject {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我想限制调用类更改NormalObject的name变量的值

但是以下代码更改了值

 ImmutableObject obj = new ImmutableObject("Siddle");

 System.out.println(obj.getObj().getName()); //prints Siddle
 obj.getObj().setName("Kelly");

 System.out.println(obj.getObj().getName()); //prints Kelly

如何限制它?

对于不可变的对象,其所有属性必须是不可变的。 它的状态一定不可改变。

要做到这一点,你必须在NormalObject上放置一个不可变的Facade,你不能直接返回一个NormalObject 返回它的方法也需要一个不同的返回类型,你不能返回NormalObject但实际上返回的行为不像NormalObject

例如:

public final class ImmutableObject {

    private final String name;

    private final NormalObject obj =  new NormalObject();

    private final ImmutableNormalObject objFacade = new ImmutableNormalObject(obj);

    public String getName() {
        return name;
    }

    public ImmutableObject(String name) {
        this.name = name;
        obj.setName(name);
    }

    public ImmutableNormalObject getObj() {

        return objFacade;
    }
}

public class NormalObject {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class ImmutableNormalObject {

    private NormalObject obj;

    public ImmutableNormalObject(Normalobject o) {
        this.obj = o;
    }

    public String getName() {
        return obj.getName();
    }
}

或者,如果复制对象并且它有一个复制构造函数(或者你可以添加一个)是可以接受的,那么你可以这样做,但复制和返回是很昂贵的。

您可以通过在getter中返回normalObject的副本来完成此操作:

public NormalObject getObj() {
    return new NormalObject(obj.getName());
    // or you can make a copy constructor:
    // return new NormalObject(obj);
}

或者您可以为NormalObject创建一个忽略名称设置器的包装器,但它会制动逻辑。

请将您的NormalObject代码更改为

public final class ImmutableObject {

    private final String name;
    // initialise it to null
    private final NormalObject obj = null;

    public String getName() {
        return name;
    }


    public ImmutableObject(String name) {
        this.name = name;
        // use the Constructor for setting name only once during initialization of ImmutableObject via its constructor
        obj =  new NormalObject(name);

        //obj.setName(name);
    }


    public NormalObject getObj() {

        NormalObject tempObj = obj;
        return tempObj;
    }
}

NormalObject类

public class NormalObject {

    private String name;
    public NormalObject(name){
     this.name = name;
    }
    public String getName() {
        return name;
    }
    //Remove any setter on NormalObject
    /*public void setName(String name) {
        this.name = name;
    }*/

}

在不可变对象中,如果用户尝试更改Object的状态。 要么你不允许或返回一个新的Immutable类实例。

所以,因为Date是一个可变类。 您可以在日期周围创建一个不可变的包装器,并且您只能公开那些可以在Immutable-Date的透视图中使用的方法,但是您返回一个新的Immutable类实例,其中包含新Date的已更改属性。

我不认为Immutable变量需要final,因为它已经是private和Immutable。

示例:

public class Main{

  private ImmutableDate immutableDate;

  public Main() {
    this.immutableDate = new ImmutableDate(new Date());
  }

  public Main(Date date){
    this.immutableDate = new ImmutableDate(date);
  }

  public ImmutableDate getDate() {
    return immutableDate;
  }

  public class ImmutableDate{
    // private constructor, so this can only be instantiated within the outer class
    // therefore, final keyword not required for Date, as no access given to the variable
    private Date date;
    private ImmutableDate(Date date) {
      this.date = date;
    }

    // Example methods from Date, that are required for our Immutable implementation

    public Main setTime(long time){
      Date date1 = new Date();
      date1.setTime(time);
      return new Main(date1);
    }

    @Override
    public String toString() {
      return date.toString();
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM