2016-02-04 179 views
1

我想使bean不可变并且传统方法是使所有字段都为final并在构造函数中设置它们的值。将可变对象转换为不可变对象

在我看来这很好,除非有很多领域需要通过一些复杂的逻辑来相互依赖地计算,或者当多个服务需要参与设置值。

工厂是另一种方法,但我不能拿出一个整洁的模型,避免太多的代码。

我想要做的是创建一个可变的bean实例,一旦它完全填充,我想“烘烤”它,即使它不可变。

有没有办法来改变在运行时更改的字段从non-finalfinal实例没有子等

我相当肯定不能用标准的Java /反射只是这样做,但我怀疑它可能可以使用一些字节码更改,如javassist等。

一个漂亮整洁的工厂模式可能会蜱太...

+3

听起来你正在寻找的“建设者”的格局 – tddmonkey

+1

为什么不计算_outside_你豆?参与设置值的多种服务看起来有点像你可能能够改进你的结构。 – Marvin

+0

看看“Person.java with Nested Person.Builder”这里http://www.javaworld.com/article/2074938/core-java/too-many-parameters-in-java-methods-part-3- builder-pattern.html - 你想要什么? –

回答

2

约书亚布洛赫在他的书中,有效的Java,第二版,在第二章中的“创建和销毁Java对象解决了这个问题“。 You can view an example taken from his book here

// Builder Pattern 
public class NutritionFacts { 
    private final int servingSize; 
    private final int servings; 
    private final int calories; 
    private final int fat; 
    private final int sodium; 
    private final int carbohydrate; 

    public static class Builder { 
     // Required parameters 
     private final int servingSize; 
     private final int servings; 

     // Optional parameters - initialized to default values 
     private int calories  = 0; 
     private int fat   = 0; 
     private int carbohydrate = 0; 
     private int sodium  = 0; 

     public Builder(int servingSize, int servings) { 
      this.servingSize = servingSize; 
      this.servings = servings; 
     } 

     public Builder calories(int val) 
      { calories = val;  return this; } 
     public Builder fat(int val) 
      { fat = val;   return this; } 
     public Builder carbohydrate(int val) 
      { carbohydrate = val; return this; } 
     public Builder sodium(int val) 
      { sodium = val;  return this; } 

     public NutritionFacts build() { 
      return new NutritionFacts(this); 
     } 
    } 

    private NutritionFacts(Builder builder) { 
     servingSize = builder.servingSize; 
     servings  = builder.servings; 
     calories  = builder.calories; 
     fat   = builder.fat; 
     sodium  = builder.sodium; 
     carbohydrate = builder.carbohydrate; 
    } 
} 

一个例子使用此对象是:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build(); 

正如可以从上面的例子中看到的,可以首先构建成一个不可变之前创建一个可变对象目的。该对象的构建器也可以进行调整并重新用于生成多个不可变对象。例如:

NutritionFacts.Builder food = new NutritionFacts.Builder(1, 1); 
NutritionFacts salad = food.calories(100).build(); 
NutritionFacts bigMac = food.calories(1000).build();