如何在Java中装饰对象

时间:2011-01-26 16:35:44

标签: java decorator

快速背景

我有两个(大)POJO列表被传递到一个方法,我需要确保两个列表中的唯一性。我能看到的最好的解决方案是构造两个集合并检查它们的交集是否为空。

问题

对于此方法的上下文和单独的此方法,我需要覆盖相关POJO的equalshashcode方法。

我在寻找什么

这似乎是装饰现有物品的主要候选人。我查看了Guava's ForwardingObject,但它似乎最适合委托实现给定接口的对象,而不是我的情况。总的来说,我正在寻找一种解决方案......

  1. 避免处理大型POJO(复制构造函数)中的所有字段。
  2. 易于理解和维护
  3. 为了这个方法而避免创建一个扩展POJO的全新类

3 个答案:

答案 0 :(得分:3)

我只是选择了一个包装类。

创建一个在构造函数中使用POJO实例化的新类。它不会复制POJO,只保留对原始的引用。然后在该包装类中编写equals和hashcode。

这样的事情:

public class MySpecialWrapper{
  private final BigPojo delegate;

  public MySpecialWrapper(BigPojo pojo){
    this.delegate = pojo;
  }

  public int hashCode(){
    //insert special impl here.
  }

  public boolean equals(Object o){
    //insert special impl here.
  }
}

将包装类的实例放入您的集合中,并将其用于唯一性验证。如果您在发生故障时需要访问有问题的POJO,请添加一个访问器方法(getDelegate)。

答案 1 :(得分:2)

一个简单的解决方案是为每个POJO类创建一个包装类。包装器保存对POJO实例的引用,并定义equals和hashcode方法,这些方法根据POJO中的相应字段计算它们的值。然后你可以使用普通的Collections类。

答案 2 :(得分:0)

您可以使用动态代理来包装每个元素:

class VeryBigPOJO {}

interface PojoWrapper {
  VeryBigPOJO getPojo();
}

class MyHandler implements InvocationHandler {
    private VeryBigPOJO ob;

    public MyHandler( VeryBigPOJO ob ) {
        this.ob = ob;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        if( method.getName().equals( "getPojo") )
            return ob;
        if( method.getName().equals( "equals") )
            //calculate equals
        if( method.getName().equals( "hashCode") )
            //calculate hashCode
    }
}

然后将对象包装到这些动态代理中:

VeryBigPOJO pojo = ...;
PojoWrapper wrapper =  Proxy.newProxyInstance( MyHandler.class.getClassLoader(), new Class[] { PojoWrapper.class}, new MyWrapper( pojo ) )

现在,您可以将wrapper个对象添加到HashSet

但是,从大型pojo中构造一个较小的,不可变的id对象会不会更容易?它肯定会更具可读性。