////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
public interface HasFriendship
<Owner extends HasFriendship
<Owner, Friend
>, Friend
extends HasFriendship
<Friend, Owner
>> {
Friendship
<Owner,
?> friendship
(Class friendClass
);
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
public class Friendship
<Owner extends HasFriendship, Friend
extends HasFriendship
>
implements HasFriend
<Owner, Friend
> {
Friend friend;
final Class<Friend> friendClass;
final Class<Owner> ownerClass;
public Friendship
(Owner owner, Class
<Friend
> friendClass
) {
this.owner = owner;
this.friendClass = friendClass;
this.ownerClass = (Class<Owner>) owner.getClass();
}
@Override
public Owner set
(Friend newFriend
) {
if (null != newFriend) {
if (null != newFriend.friendship(ownerClass).friend)
newFriend.friendship(ownerClass).friend.friendship(friendClass).friend = null;
if (null != this.friend)
this.friend.friendship(ownerClass).friend = null;
newFriend.friendship(ownerClass).friend = owner;
this.friend = newFriend;
}
else if (null == newFriend) {
if (null != this.friend)
this.friend.friendship(ownerClass).friend = null;
this.friend = null;
}
return owner;
}
public Friend get() {
return friend;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import lombok.*;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
public class A implements HasName<A>, HasFriendship {
@Getter @Setter
this.name = name;
}
Friendship<A, B> fb = new Friendship<>(this, B.class);
@Override
public Friendship<A, B> friendship(Class friendClass) {
return fb;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import lombok.*;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
public class B implements HasName<B>, HasFriendship {
@Getter @Setter
this.name = name;
}
Friendship<B, A> fa = new Friendship<>(this, A.class);
@Override
public Friendship<B, A> friendship(Class friendClass) {
if (friendClass.isAssignableFrom(A.class))
return fa;
return null;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
public class Camera implements HasFriendship {
public final Friendship<Camera, Controller> controller =
new Friendship<>(this, Controller.class);
@Override
public Friendship<Camera, Controller> friendship(Class cClass) {
return controller;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
public class Controller implements HasFriendship {
public final Friendship<Controller, Camera> camera = new Friendship<>(this, Camera.class);
public final Friendship<Controller, Mouse> mouse = new Friendship<>(this, Mouse.class);
public Friendship<Controller, ?> friendship(Class friendClass) {
if (friendClass.isAssignableFrom(Mouse.class))
return mouse;
if (friendClass.isAssignableFrom(Camera.class))
return camera;
return null;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import lombok.experimental.Accessors;
@Accessors(fluent = true)
public class Mouse implements HasFriendship {
public final Friendship<Mouse, Controller> controller = new Friendship<>(this, Controller.class);
@Override
public Friendship<Mouse, ?> friendship(Class friendClass) {
return controller;
}
}
////////////////////////////////////////////////////////////////////////////////
package pl.glx.pattern;
import static pl.glx.common.Helpers.*;
import static pl.glx.common.Constants.*;
public class AB {
static
private void showObjects
(String what, A a1, B b1, A a2, B b2
) {
println(charRepeat('-', 20) + SPACE + what);
printf("a1 b: %s", null != a1.fb.get() ? a1.fb.get().name() : null);
printf("b1 a: %s", null != b1.fa.get() ? b1.fa.get().name() : null);
printf("a2 b: %s", null != a2.fb.get() ? a2.fb.get().name() : null);
printf("b2 a: %s", null != b2.fa.get() ? b2.fa.get().name() : null);
}
public static void main
(String[] args
) {
A a1 = new A("a1");
B b1 = new B("b1");
A a2 = new A("a2");
B b2 = new B("b2");
a1.fb.set(b1);
b2.fa.set(a2);
showObjects("a1.fb.set(b1); b2.fa.set(a2);", a1, b1, a2, b2);
a1.fb.set(b2);
showObjects("a1.fb.set(b2);", a1, b1, a2, b2);
b2.fa.set(a2);
showObjects("b2.fa.set(a2);", a1, b1, a2, b2);
b1.fa.set(null);
showObjects("b1.fa.set(null);", a1, b1, a2, b2);
a2.fb.set(null);
showObjects("a2.fb.set(null);", a1, b1, a2, b2);
Camera cam = new Camera();
Controller ctrl = new Controller();
Mouse mice = new Mouse();
cam.controller.set(ctrl);
ctrl.mouse.set(mice);
assert cam == ctrl.camera.get() : "cam != ctrl.camera.get()";
assert ctrl == cam.controller.get() : "ctrl != cam.controller.get()";
assert mice == ctrl.mouse.get() : "mice != ctrl.mouse.get()";
cam.controller.set(null);
assert null == ctrl.camera.get() : "null != ctrl.camera.get()";
}
}
////////////////////////////////////////////////////////////////////////////////