只是拿了一个比较典型的例子(订单),类似这种例子非常的多。当然不是说适用于所有的情况。
只是刚才回帖之后,一时兴起拿出来与大家做一个小的分享。不知道对你是否有用。public class Order {

private String name;
//
private Set<OrderLine> orderLines = new HashSet<OrderLine>(); public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} /**
 * 因为这是一个domain对象,贯穿你整个项目,不知你是否在意过这样的设计。
 * 这样的设计对你是否有用呢?
 * 用户:表示API调用者。 
 */

public Set<OrderLine> getOrderLines() {
/*
 * 1.防止用户任意修改订单行的内容,强制要求用户使用当前类提供的API修改订单行
 * 2.getOrderLines()绝对不为null,有可能getOrderLines().isEmpty()为true
 * 用在你的程序中不会出现if(getOrderLines() == null && getOrderLines().isEmpty()),
 * 只会出现if(getOrderLines().isEmpty())
 */
return Collections.unmodifiableSet(orderLines);
} //-----------------------提供API修改Order by OrderLine----------------------------//
public void addOrderLine(OrderLine orderLine) {
//
orderLines.add(orderLine);
} public void removeOrderLine(OrderLine orderLine) {
// ...
}
//-----------------------提供API修改Order by OrderLine----------------------------//

public void setOrderLines(Set<OrderLine> orderLines) {
// this.orderLines = orderLines;
// 为什么没有向上面来做,是因为如果是这样赋值的话那么两个对象就是同一个引用了。
// 用户修改orderLines,this.orderLines也同样会被修改。
// 而提供这个类期望用户通过该类提供的接口来修改orderLines。
orderLines.addAll(orderLines);
}}

解决方案 »

  1.   

    PS:因为这是写的一个简单的DEMO,主要是想传递这种思想,代码不也非常的严密,设计不是非常全面。
    但是设计的面都是差不多的。并且这些对象都随着业务的改变而改变。所以我只是写了一个大概。
      

  2.   

    不是副本,是另一个引用指向这个set。一个不可以被改变的引用。
      

  3.   

    READ IT AGAIN
    “用在你的程序中不会出现if(getOrderLines() == null && getOrderLines().isEmpty()),”
    当然不可能出现,只可能出现NPE,如果出现true的话,那就是getOrderLines()方法不是幂等的。另外,建议使用linkedhashset,以保持顺序。同时,考虑是否有多线程问题。单单这一段代码,在多线程下面会有问题
      

  4.   

    有点小疑问,为什么要在domain对象做这样的处理,感觉domain对象越纯越好,只有属性和get,set方法,曾经使用hibenate时在domain对象做了简单的处理 return name==null?"":name;但是每次加载完对象后会发出大量的update语句,因为hibenate会认为是脏数据了,同样按楼主的代码orderLines对象也改变了是否会引起刷新? (解决遇见的那个问题是通过将property access改为field access .....)
      

  5.   


    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;public class Order<T> {// 顺便泛化吧    private String name;
        //
        private Set<T> orderLines = new HashSet<T>();    public String getName() {
    return name;
        }    public void setName(String name) {
    this.name = name;
        }    /*
         * synchronized (mutex) {
         *  }
         */
        public boolean addOrderLine(T orderLine) {// 返回值改为布尔值好一点
    if (orderLine == null)
        return false;
    return orderLines.add(orderLine);
        }    public boolean removeOrderLine(T orderLine) {// 返回值改为布尔值好一点 if (orderLine == null)
        return false;
    return orderLines.remove(orderLine);
        }    // 还可以适当添加clear() removeAll(Collection<T> c),addAll(Collection<T> c)
        // 还可以适当添加 size iterator(),contains(Object o) toArray()常用方法    public void setOrderLines(Set<T> orderLines) {
    orderLines.addAll(orderLines);// 这里写成allAll感觉怪怪的,写成this.orderLines =
    // orderLines
        }    public Set<T> getOrderLines() {
    return Collections.unmodifiableSet(orderLines);
        }    // ////////////////////////////////////////////////////////////////////    private Order() {    }    private Order(String name) {
    this.name = name;
        }    private Order(Set<T> orderLines) {
    this.orderLines = orderLines;
        }    private Order(String name, Set<T> orderLines) {
    this.name = name;
    this.orderLines = orderLines;
        }    public Order<T> getInstance() {
    return new Order<T>();
        }    public Order<T> getInstance(String name) {
    return new Order<T>(name);
        }    public Order<T> getInstance(Set<T> orderLines) {
    return new Order<T>(orderLines);
        }    public Order<T> getInstance(String name, Set<T> orderLines) {
    return new Order<T>(name, orderLines);
        }    public String toString() {//
    return String.format("name = %s ", name, orderLines);
        }
    }
      

  6.   

    对于一个实体对象是否会存在线程的问题,这应该是和业务挂钩的吧。
    假设线程A使用:
    Order order = new Order();
    而线程B使用:
    Order order = new Order();这两个线程都有一个order对象,假设这两个对象对应的流水号是一样的。
    但是却是两个完全不同的对象应该不存在线程安全的问题。当然如果有特殊的情况需要多个线程共享同一个order对象,那么就必须要通过其它的手段来达成目的,那么在哪里做上线程同步也同样可以避免线程带来的问题。
    所以我觉得这个domain没有考虑线程方面的问题,这没有问题。
    对于朋友所说的使用LinkedHashSet,我觉得这就得根据需求来选择了。
      

  7.   

    Java菜鸟学习了。return Collections.unmodifiableSet(orderLines);