Reputation: 4280
What I want to achieve, say we have an object jacket
and as we know only single person can use a jacket at time, in code:
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
The solution that I have right now is to create a "proxy" that will wrap one "physical" jacket:
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);
}
}
All above classes are in the same package, but they will be used from outside (in other words we may tread package scope like private here):
JacketFactory factory = new JacketFactory(); // crate is package scoped
JacketOwnership jacket = JacketOwnership.createJacket(factory);
jacket.use();
JacketOwnership nowJacketIsMine = jacket.takePossession();
nowJacketIsMine.use();
I feel this solution is a bit overcompilcated is there a simpler/better way?
PS. I don't need to have bulletproof solution - reflection may break it, it just needs to be save from Java language point of view...
Upvotes: 2
Views: 525
Reputation: 418
I think what you need is relationship OWNER (0-1) <---> (*)JACKET. My assumption is owner can have zero to many Jackets and Jacket can be owned by maximum one owner.
I propose following simple code. Adding other complexities can restrict unnecessary access to methods (to avoid API misuse) e.g. the transfer needs to be as a single transaction and accessing only set method will spoil the relationship.
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);
}
Upvotes: 0
Reputation: 425
just write sellJacketTo method in this way:
void sellJacketTo(Person p){
p.jacket = this.jacket;
this.jacket = null;
}
Upvotes: -1
Reputation: 1658
what about decoupling all of this?
just have your jacket class, with info regarding jacket itself (color, size, whatever). no method that does business logic.
then your person class, with info regarding person itself (name, age, whatever). no method that does business logic.
then your jacketowner entity, which you can model as you prefer. then you can just have a repo (inventory) of jacketowners and have the constraints as you need (as for example not allowing same jacket to appear twice). in the simplest form, a repo of jacketowners could consist on a
HashMap<Jacket, Person>
since you decoupled jacket-person and removed business inside the entities, you can easily have a repo of all the "links" and just add constraints on them as a whole as part of a service (where you have your business logic).
Upvotes: 2