在Java中实现Trait模式的更好方法是什么?

时间:2016-10-12 02:03:21

标签: java traits

我想允许我的域类拥有" injectable"行为。

这个想法基于es4j协议https://es4j.eventsourcing.com/docs/master/core_concepts/domain_protocol.html

但是我使用AxonFramework,所以我需要自己实现它。

目前我采用的方法是#34;协议处理程序"这基于接口。

示例DomainProtocol(伪代码)

public interface NameProtocol extends ProtocolBase {
    public String getName();
    public void setName(String name);

    default boolean handleNameProtocol(DomainEventMessage eventMessage){
        // pseudocode
        if(eventMessage == NameChangedEvent) setName(eventMessage.getName());
    }

}

然后,基本聚合类型将根据类名或注释来初始化处理程序。 目前它基于MethodHandle methodHandle = lookup.findVirtual(aggregateClazz, "handle"+interf.getSimpleName(), MethodType.methodType(boolean.class, DomainEventMessage.class));

不幸的是,接口只允许公共方法,这会导致一些内部方法在外面可见,所以我创建了一个类ProtocolHelper来强制执行这些方法的调用者:

public class ProtocolHelper extends SecurityManager {
public static final ProtocolHelper INSTANCE = new ProtocolHelper();

public Class[] getCallingClasses() {
    return getClassContext();
}


public static void enforcePrivate(){
    Class[] classes = ProtocolHelper.INSTANCE.getCallingClasses();
    // 0 1 - this class
    // 2 - the protected method
    // 3 - should be a class that extends ProtocolBase (or same class as 2)
    if(
        !ProtocolBase.class.isAssignableFrom(classes[3])
        &&
        !classes[2].equals(classes[3])
    )
        throw new RuntimeException("This method can only be called by the protocol handler !");
}
}

然后像这样使用它:

@Deprecated
@Override
public void setName(String name) {
    ProtocolHelper.enforcePrivate();
    this.name = name;
}

显然这种方法非常可怕,但经过多个小时的试验和错误后,这是我能想到的最佳解决方案。

我尽量不在任何地方使用反射,但在初始化时,我不想让Annotation Processor复杂化构建..

感觉就像Java故意试图阻止我这样做,静态抽象类不被继承,不允许受保护的接口方法等等。

有没有办法实现我想做的事情?

这个解决方案是否有任何我不知道的问题(除了它"丑陋"或"不是kosher")

0 个答案:

没有答案