2013-07-25 102 views
-2

我有一个关于如何避免Java对象的副作用的问题。 让我们假设我有一个实例myObjectMyObject。我想通过一系列方法/命令来处理myobject,并且在每个命令级别,我想用方法/命令已计算的内容丰富myObject避免副作用的最佳做法

在这里,类myObject的是的一个实例:

public class MyObject { 
    private int resultOfCommand1; 
    private int resultOfCommand2; 
    private int resultOfCommand3; 
    private int resultOfCommand4; 
    .... 
    .... 
} 

这里是方法/命令其中myObject的必须通过进行处理:

private MyObject command1(MyObject myObject) { 
    return myObject.setRresultOfCommand1(1); 
} 
private MyObject command2(MyObject myObject) { 
    return myObject.setRresultOfCommand2(2); 
} 
private MyObject command3(MyObject myObject) { 
    return myObject.setRresultOfCommand3(3); 
} 
private MyObject command4(MyObject myObject) { 
    return myObject.setRresultOfCommand4(4); 
} 

所以示出的设计上面确实有副作用,我想避免这样的事情。

有人能告诉我避免副作用的最好方法吗?总是使用作为参数传递的对象的副本(在本例中为myObject)更好吗,对副本进行更改并返回它? 有没有一种保证多线程安全的最佳方式?

任何帮助,将不胜感激。 Horace

+1

你所做的只是看起来像过分复杂的getter和setter ...然后,因为你提到了线程。使用同步 – chancea

+0

你有没有考虑过使它成为管道模式?将对象传递给每个修改对象的命令类数组。只有在每个正在处理的命令中都没有肉的情况下,它才会变得过于分散。另外,要执行的命令可以很容易地变化。在netty中查看这种模式的实现,http://docs.jboss.org/netty/3.2/api/org/jboss/netty/channel/ChannelPipeline.html – Raji

回答

2

如果你想避免副作用,设置一个值的方法不能改变实例,而是返回一个新的实例(副本)。在该方法中,您使用构造函数来设置所有(最终)值。

实施例:

class C { 
    private final int x; 
    private final int y; 

    public C(int _x) { 
     super(); 
     this.x = _x; 
     this.y = -1; 
    } 

    public C(int _x, int _y) { 
     super(); 
     this.x = _x; 
     this.y = _y; 
    } 

    public C setY(int _y) { 
     return new C(this.x, _y); 
    } 
} 

为了防止副作用,只是声明的字段作为final。如果所有字段都是final,则值(在基本类型的情况下)和对象引用是不可变的。在对象引用的情况下,该对象也必须是不可变的,以实现“完全不变性”。

所以你不要更改副本,但你构造与新值的副本。

现在可以安全地传递不可变实例;它不能改变,所以它是线程安全的。

相关问题