Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中只允许对对象实例进行单一引用的最佳方法_Java_Oop - Fatal编程技术网

Java中只允许对对象实例进行单一引用的最佳方法

Java中只允许对对象实例进行单一引用的最佳方法,java,oop,Java,Oop,我想要实现的是,假设我们有一个对象夹克,我们知道,在代码中,只有一个人可以在同一时间使用夹克: Jacket jacket = createJacket(); bob.buy(jacket); bob.useJacket(); // here bob has a reference to jacket // now let's say bob is selling his jacket bob.sellJacketTo(alice); // now how to prevent bob

我想要实现的是,假设我们有一个对象
夹克
,我们知道,在代码中,只有一个人可以在同一时间使用夹克:

Jacket jacket = createJacket();

bob.buy(jacket);
bob.useJacket(); // here bob has a reference to jacket

// now let's say bob is selling his jacket

bob.sellJacketTo(alice);

// now how to prevent bob from saving reference to
// jacket instance, because now it is alice jacket and
// only alice can use it
我现在的解决方案是创建一个“代理”,它将包裹一个“物理”护套:

以上所有类都在同一个包中,但它们将从外部使用(换句话说,我们可以像这里的private一样处理包范围):

我觉得这个解决方案有点过度编译了有没有更简单/更好的方法


另外,我不需要防弹的解决方案——反射可能会破坏它,只需要从Java语言的角度保存它…

如何将所有这些解耦

只需拥有你的夹克等级,以及关于夹克本身的信息(颜色、尺寸等)。没有处理业务逻辑的方法

然后是person类,其中包含有关person本身的信息(姓名、年龄等)。没有处理业务逻辑的方法

然后是jacketowner实体,您可以根据自己的喜好对其进行建模。然后,您可以对jacketowners进行回购(库存),并根据需要设置约束条件(例如,不允许同一个jacketowners出现两次)。最简单的形式是,房屋所有人的回购协议可以包含在

HashMap<Jacket, Person>
HashMap

由于您分离了jacket person并删除了实体内部的业务,因此您可以轻松地对所有“链接”进行回购,只需将它们作为服务的一部分(在您有业务逻辑的地方)对其添加约束即可。

只需以以下方式编写sellJacketTo方法:

void sellJacketTo(Person p){
     p.jacket = this.jacket;
     this.jacket = null;
}

我想你需要的是关系 业主(0-1)(*)导管架。 我的假设是,所有者可以拥有零到多个夹克,并且夹克最多可以由一个所有者拥有

我建议使用以下简单代码。增加其他复杂性可能会限制对方法的不必要访问(以避免API滥用),例如,传输需要作为单个事务进行,并且仅访问set方法会破坏关系

public class Jacket {
    private Owner owner;
    private int id;
    public Jacket(int id) {
        this.id = id;
    }

    public Owner getOwner() {
        return owner;
    }

    public void setOwner(Owner owner) {
        this.owner = owner;
    }
}

public class Owner {
    private String name;
    private Set<Jacket> jackets = new HashSet<>();;

    public Owner(String name) {
        this.name = name;
    }

    public void sellJacketTo(Owner buyer) {
        if (jackets.size() > 0) {
            Jacket jacketForSell = new ArrayList<Jacket>(jackets).get(0);
            jackets.remove(jacketForSell);
            jacketForSell.setOwner(null);
            buyer.add(jacketForSell);
        }
    }

    public void add(Jacket jacket) {
        if (jacket.getOwner() == null) {
            this.jackets.add(jacket);
            jacket.setOwner(this);
        }
    }
}

public static void main(String[] args) {
    Jacket j1 = new Jacket(1);
    Jacket j2 = new Jacket(2);
    Jacket j3 = new Jacket(3);

    Owner o1 = new Owner("O1");
    Owner o2 = new Owner("O2");

    o1.add(j1);
    o1.add(j2);
    o2.add(j1);
    o2.add(j3);

    o1.sellJacketTo(o2);

    System.out.println(o1);
    System.out.println(o2);
}
公共级夹克{
私人业主;
私有int-id;
公共夹克(内部id){
this.id=id;
}
公共所有者getOwner(){
归还所有人;
}
公共无效集合所有者(所有者){
this.owner=所有者;
}
}
公共类所有者{
私有字符串名称;
私有集夹克=新HashSet();;
公共所有者(字符串名称){
this.name=名称;
}
Jacketto(业主-买方)公共空间{
如果(夹套尺寸()>0){
导管架jacketForSell=新阵列列表(导管架)。获取(0);
导管架。移除(导管架/套管);
jacketForSell.setOwner(空);
买方。添加(jacketForSell);
}
}
公共空间添加(夹套){
if(jacket.getOwner()==null){
本.夹套.添加(夹套);
导管架所有人(本);
}
}
}
公共静态void main(字符串[]args){
护套j1=新护套(1);
导管架j2=新导管架(2);
导管架j3=新导管架(3);
所有者o1=新所有者(“o1”);
所有者o2=新所有者(“o2”);
o1.添加(j1);
o1.添加(j2);
o2.添加(j1);
o2.添加(j3);
o1.Jacketto(o2);
系统输出打印项次(o1);
系统输出打印Ln(o2);
}

您正在寻找的对象被称为“可转移对象”,据我所知,该语言和jvm没有提供任何方法来获取这些对象。在
.sellJacketTo()
方法中,使用
this.jacket=null从
bob
中移除护套
并将夹克指定给
alice
您可以将“夹克”封装在其所有者内部,而不让引用转义。也就是说,不要在内部创建一个
bob.buy(jacket)
而创建一个
bob.buyNewJacket()
。您可以轻松地在BOB之间传输它,因为同一类的成员仍然可以访问私有成员。不要使用单例。在Java中,您永远不能保证对给定对象只有一个引用。您所能做的最好的事情是将“拥有的对象”包装在您自己的类中,而该类不会复制引用。反射将打破这一要求。这不是关于简单的所有权(这只是一个例子),我需要的是一种机制,它允许我保证只有一个对对象的引用(如在单例模式中),而且这个引用在转移后可以在对象和前一个所有者之间转移(即使是由邪恶的程序员编写)将无法再次访问此对象。是的,这是一个非常困难的问题,与并发有关。。。
void sellJacketTo(Person p){
     p.jacket = this.jacket;
     this.jacket = null;
}
public class Jacket {
    private Owner owner;
    private int id;
    public Jacket(int id) {
        this.id = id;
    }

    public Owner getOwner() {
        return owner;
    }

    public void setOwner(Owner owner) {
        this.owner = owner;
    }
}

public class Owner {
    private String name;
    private Set<Jacket> jackets = new HashSet<>();;

    public Owner(String name) {
        this.name = name;
    }

    public void sellJacketTo(Owner buyer) {
        if (jackets.size() > 0) {
            Jacket jacketForSell = new ArrayList<Jacket>(jackets).get(0);
            jackets.remove(jacketForSell);
            jacketForSell.setOwner(null);
            buyer.add(jacketForSell);
        }
    }

    public void add(Jacket jacket) {
        if (jacket.getOwner() == null) {
            this.jackets.add(jacket);
            jacket.setOwner(this);
        }
    }
}

public static void main(String[] args) {
    Jacket j1 = new Jacket(1);
    Jacket j2 = new Jacket(2);
    Jacket j3 = new Jacket(3);

    Owner o1 = new Owner("O1");
    Owner o2 = new Owner("O2");

    o1.add(j1);
    o1.add(j2);
    o2.add(j1);
    o2.add(j3);

    o1.sellJacketTo(o2);

    System.out.println(o1);
    System.out.println(o2);
}