是否有任何模式用于实现holder对象的可变和不可变版本?

时间:2014-10-30 20:41:26

标签: java design-patterns immutability

在我的应用程序中,我有几种类型的 holder 对象,其主要目的是存储异构相关数据。他们的生命周期可以分为两部分:

  1. 数据一旦可用就收集;
  2. 为持有者的剩余生命提供对存储数据的只读访问权。
  3. 使持有者不可变是非常诱人的,但是数据不能同时传递给构造函数。我看到的最简单的解决方法是创建一个holder类的两个版本,一个是可变的,另一个不是:

    public class MutableHolder {
        public int field1;
        public String field2;
        // ...
        public Object fieldN;
    }
    
    public class Holder {
        public final int field1;
        public final String field2;
        // ...
        public final Object fieldN;
    
        public Holder(MutableHolder mutableHolder) {
            this.field1 = mutableHolder.field1;
            this.field2 = mutableHolder.field2;
            // ...
            this.fieldN = mutableHolder.fieldN;
        }
    }
    

    但是,我觉得这种方法违反了DRY原则(如果我想更改任何内容,我不能忘记更新两个类的字段以及构造函数)并且容易出错。所以这是我的问题:是否有任何现有的模式,我不知道实现持有者对象的可变和不可变版本?

    修改

    我突然发现上面的代码是Builder模式的非常准确的版本(请参阅thisthis)。这让我觉得在这种情况下DRY违规被认为是可以接受的。

2 个答案:

答案 0 :(得分:1)

另一种可能的解决方案是State design pattern。因为它的主要概念是在状态改变时改变对象的行为。还允许对象在其内部状态更改时更改其行为。该对象似乎会改变其类。

在您的情况下,您可以考虑以下实施:

//maintains an instance of a ConcreteState subclass that defines the current state
public class Holder {
    //your code
}

//encapsulating the behavior associated with a particular state of the Holder
public abstract class State{
    //your code
}

//implements a behavior associated with a state of Holder
public class MutableHolderState extends State {
    //your code
}

//implements a behavior associated with a state of Holder
public class ImmutableHolderState extends State {
    //your code
}

答案 1 :(得分:1)

我也曾经磕磕绊绊过一段时间。这是我提出的一种设计模式,我没有在其他地方看到过。

public class Bob
{
    // member variables
    private int value;

    // simple constructor
    private Bob()
    {
        value(0);
    }

    // constructor with value
    private Bob(int value)
    {
        value(value);
    }

    // get value
    public final int value()
    {
        return this.value;
    }

    // set value
    private final void value(int value)
    {
        this.value = value;
    }


    // mutable class modifies base class
    public static class Mutable extends Bob
    {
        // simple constructor
        private Mutable()
        {
            super();
        }

        // constructor with value
        private Mutable(int value)
        {
            super(value);
        }

        // set value
        public final void value(int value)
        {
            super.value(value);
        }
    }


    // factory creator for immutable
    public static final Bob immutable(int value)
    {
        return new Bob(value);
    }

    // factory creator for mutable
    public static final Mutable mutable()
    {
        return new Mutable();
    }

    // another mutable factory creator
    public static final Mutable mutable(int value)
    {
        return new Mutable(value);
    }
}
  • 该类不是最终的,子类化应该是安全的。
  • 所有构造函数都必须是私有的。
  • 公共访问者应该是最终的。
  • 基类中的私有变更器应该是最终的。
  • Mutable类中的公共变异器应该是最终的。
  • 使用工厂方法构造不可变和可变对象。

这类似于子类可变模式,但由于Mutable类是内部类,因此它可以访问基类中的私有字段和方法,因此不需要保护任何可能被覆盖的内容。基类就像标准的可变类,除了构造函数和mutator是私有的。可变子类是一个薄层(每个方法都是超...)暴露了变异器。

创建不可变实例:Bob test1 = Bob.immutable(99);创建可变实例:Bob.Mutable test2 = Bob.mutable();