首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中只允许对对象实例进行单一引用的最佳方式

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

Stack Overflow用户
提问于 2017-08-09 03:56:59
回答 3查看 213关注 0票数 2

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

代码语言:javascript
复制
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

我现在的解决方案是创建一个“代理”,它将包装一个“物理”夹克:

代码语言:javascript
复制
public class Jacket implements Outerwear {
    private String color;
    private int size;

    Jacket(String color, int size) {
        this.color = color;
        this.size = size;
    }

    @Override
    public void use() {
        System.out.printf("%s jacket in size %d is warming you right now ;)", color, size);
    }
// ...
}

public class JacketOwnership implements Outerwear {
    private Jacket jacket;

    private JacketOwnership(Jacket jacket) {
        this.jacket = jacket;
    }

    public boolean isValid() {
        return (jacket != null);
    }

    @Override
    public void use() {
        if (!isValid())
            throw new IllegalStateException("You no longer own the jacket!");

        jacket.use();
    }

    public JacketOwnership takePossession() {
        Jacket tmp = this.jacket;
        this.jacket = null;

        return new JacketOwnership(tmp);
    }

    public static JacketOwnership createJacket(JacketFactory jacketFactory) {
        Jacket jacket = jacketFactory.create();
        return new JacketOwnership(jacket);
    }
}

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

代码语言:javascript
复制
    JacketFactory factory = new JacketFactory(); // crate is package scoped
    JacketOwnership jacket = JacketOwnership.createJacket(factory);

    jacket.use();

    JacketOwnership nowJacketIsMine = jacket.takePossession();
    nowJacketIsMine.use();

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

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

EN

回答 3

Stack Overflow用户

发布于 2017-08-09 05:35:48

把所有这些都解耦出来怎么样?

只要有你的夹克类,关于夹克本身的信息(颜色,尺寸,无论什么)。没有执行业务逻辑的方法。

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

然后是你的jacketowner实体,你可以根据自己的喜好来建模。然后,您只需拥有一个夹克所有者的repo (库存),并具有所需的约束(例如,不允许同一夹克出现两次)。在最简单的形式中,夹克所有者的回购可以包含在

代码语言:javascript
复制
HashMap<Jacket, Person>

由于您解耦了jacket-person并删除了实体内部的业务,因此您可以轻松地拥有所有“链接”的代码库,并只需将约束作为服务的一部分添加到整个服务中(其中您有自己的业务逻辑)。

票数 2
EN

Stack Overflow用户

发布于 2017-08-09 12:53:36

我认为你需要的是关系所有者(0-1) <->(*)夹克。我的假设是,所有者可以有零到多个夹克,夹克可以由最多一个所有者拥有。

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

代码语言:javascript
复制
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);
}
票数 0
EN

Stack Overflow用户

发布于 2017-08-09 10:16:24

只需按如下方式编写sellJacketTo方法:

代码语言:javascript
复制
void sellJacketTo(Person p){
     p.jacket = this.jacket;
     this.jacket = null;
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45577053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档