我在Java中尝试做的事实上是拥有一个接口,它是两个其他接口的组合(因此它具有来自这两个接口的方法,但它们都没有),以及然后可以一次一个地交换两个子接口,因此当进行改变时,保留来自两个接口之一的所有方法,而来自另一个接口的所有方法被交换为不同的接口。由于泛型正在处理切换,因此无需进行转换以获取新方法或删除旧方法。
因此,我们开始使用接口AA
,它是接口LeftA
和RightA
的组合,为其提供方法methodLeftA
和{{1然后我们调用methodRightA
,现在我们有接口selectLeftType(B)
,它是接口BA
和LeftB
的组合,为它提供方法RightA
和methodLeftB
。使用泛型,这基本上允许我做类似以下的事情:methodRightA
我已经制定了一个可以正常工作的实现,我将在这里进一步展示,但代码非常冗长。只需要执行类型A,B和C.已经有30个文件,要添加D,需要添加16个新文件并编辑17个现有文件。要在此之后添加E,需要添加20个新文件并编辑26个现有文件。因此,虽然这对于少数选项来说是可以接受的,但它会迅速失控,而不仅仅是几个选项。所以我的问题是,是否有一些更简单,更清洁的方法可以做到这一点?
注意:这是使用Java 7构建的,但我对使用Java 8功能的实现持开放态度。
我目前的实施如下(就像我之前说过的那样,很长):
BaseImpl.java
getStartState().methodLeftA().methodRightA().selectLeftType(B).methodLeftB().methodRightA()
Selector.java
package test;
class BaseImpl<CURRENT_INTERFACE> implements Combo<CURRENT_INTERFACE> {
protected <T extends Combo<?>> T
selectLeftTypeBase(Selector<?, ?, ?, ?, ?, ?> selector, Class<T> cls) {
System.out.println("Switch left type. New class: " + cls.getSimpleName());
return selectTypeBase(cls);
}
protected <T extends Combo<?>> T
selectRightTypeBase(Selector<?, ?, ?, ?, ?, ?> selector, Class<T> cls) {
System.out.println("Switch right type. New class: " + cls.getSimpleName());
return selectTypeBase(cls);
}
private <T extends Combo<?>> T selectTypeBase(Class<T> cls) {
try {
return cls.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodLeftA() {
System.out.println("Left A specific stuff.");
return (CURRENT_INTERFACE) this;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodLeftB() {
System.out.println("Left B specific stuff.");
return (CURRENT_INTERFACE) this;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodLeftC() {
System.out.println("Left C specific stuff.");
return (CURRENT_INTERFACE) this;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodRightA() {
System.out.println("Right A specific stuff.");
return (CURRENT_INTERFACE) this;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodRightB() {
System.out.println("Right B specific stuff.");
return (CURRENT_INTERFACE) this;
}
@SuppressWarnings("unchecked")
public CURRENT_INTERFACE methodRightC() {
System.out.println("Right C specific stuff.");
return (CURRENT_INTERFACE) this;
}
}
Util.java
package test;
public final class Selector<
LEFT_A_TYPE extends LeftA<LEFT_A_TYPE> & Combo<LEFT_A_TYPE>,
RIGHT_A_TYPE extends RightA<RIGHT_A_TYPE> & Combo<RIGHT_A_TYPE>,
LEFT_B_TYPE extends LeftB<LEFT_B_TYPE> & Combo<LEFT_B_TYPE>,
RIGHT_B_TYPE extends RightB<RIGHT_B_TYPE> & Combo<RIGHT_B_TYPE>,
LEFT_C_TYPE extends LeftC<LEFT_C_TYPE> & Combo<LEFT_C_TYPE>,
RIGHT_C_TYPE extends RightC<RIGHT_C_TYPE> & Combo<RIGHT_C_TYPE>> {
public static final Selector<AA, AA, BA, AB, CA, AC> A =
new Selector<AA, AA, BA, AB, CA, AC>(
AAImpl.class, AAImpl.class,
BAImpl.class, ABImpl.class,
CAImpl.class, ACImpl.class);
public static final Selector<AB, BA, BB, BB, CB, BC> B =
new Selector<AB, BA, BB, BB, CB, BC>(
ABImpl.class, BAImpl.class,
BBImpl.class, BBImpl.class,
CBImpl.class, BCImpl.class);
public static final Selector<AC, CA, BC, CB, CC, CC> C =
new Selector<AC, CA, BC, CB, CC, CC>(
ACImpl.class, CAImpl.class,
BCImpl.class, CBImpl.class,
CCImpl.class, CCImpl.class);
private final Class<? extends LEFT_A_TYPE> leftATypeClass;
private final Class<? extends LEFT_B_TYPE> leftBTypeClass;
private final Class<? extends LEFT_C_TYPE> leftCTypeClass;
private final Class<? extends RIGHT_A_TYPE> rightATypeClass;
private final Class<? extends RIGHT_B_TYPE> rightBTypeClass;
private final Class<? extends RIGHT_C_TYPE> rightCTypeClass;
private Selector(
Class<? extends LEFT_A_TYPE> leftATypeClass,
Class<? extends RIGHT_A_TYPE> rightATypeClass,
Class<? extends LEFT_B_TYPE> leftBTypeClass,
Class<? extends RIGHT_B_TYPE> rightBTypeClass,
Class<? extends LEFT_C_TYPE> leftCTypeClass,
Class<? extends RIGHT_C_TYPE> rightCTypeClass) {
this.leftATypeClass = leftATypeClass;
this.leftBTypeClass = leftBTypeClass;
this.leftCTypeClass = leftCTypeClass;
this.rightATypeClass = rightATypeClass;
this.rightBTypeClass = rightBTypeClass;
this.rightCTypeClass = rightCTypeClass;
}
public Class<? extends LEFT_A_TYPE> getLeftATypeClass() {
return leftATypeClass;
}
public Class<? extends LEFT_B_TYPE> getLeftBTypeClass() {
return leftBTypeClass;
}
public Class<? extends LEFT_C_TYPE> getLeftCTypeClass() {
return leftCTypeClass;
}
public Class<? extends RIGHT_A_TYPE> getRightATypeClass() {
return rightATypeClass;
}
public Class<? extends RIGHT_B_TYPE> getRightBTypeClass() {
return rightBTypeClass;
}
public Class<? extends RIGHT_C_TYPE> getRightCTypeClass() {
return rightCTypeClass;
}
}
Left.java
package test;
public final class Util {
private Util() {}
public static AA getStartState() {
return new AAImpl();
}
}
Right.java
package test;
public interface Left<CURRENT_INTERFACE> { }
Combo.java
package test;
public interface Right<CURRENT_INTERFACE> { }
LeftA.java
package test;
public interface Combo<CURRENT_INTERFACE> extends
Left<CURRENT_INTERFACE>,
Right<CURRENT_INTERFACE> { }
LeftB.java
package test;
public interface LeftA<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodLeftA();
public <T extends Combo<T> & LeftA<T>> T
selectRightType(Selector<T, ?, ?, ?, ?, ?> selector);
}
LeftC.java
package test;
public interface LeftB<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodLeftB();
public <T extends Combo<T> & LeftB<T>> T
selectRightType(Selector<?, ?, T, ?, ?, ?> selector);
}
RightA.java
package test;
public interface LeftC<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodLeftC();
public <T extends Combo<T> & LeftC<T>> T
selectRightType(Selector<?, ?, ?, ?, T, ?> selector);
}
RightB.java
package test;
public interface RightA<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodRightA();
public <T extends Combo<T> & RightA<T>> T
selectLeftType(Selector<?, T, ?, ?, ?, ?> selector);
}
RightC.java
package test;
public interface RightB<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodRightB();
public <T extends Combo<T> & RightB<T>> T
selectLeftType(Selector<?, ?, ?, T, ?, ?> selector);
}
AA.java
package test;
public interface RightC<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
public CURRENT_INTERFACE methodRightC();
public <T extends Combo<T> & RightC<T>> T
selectLeftType(Selector<?, ?, ?, ?, ?, T> selector);
}
AAImpl.java
package test;
public interface AA extends Combo<AA>, LeftA<AA>, RightA<AA> { }
AB.java
package test;
final class AAImpl extends BaseImpl<AA> implements AA {
@Override
public <T extends Combo<T> & LeftA<T>> T
selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftATypeClass());
}
@Override
public <T extends Combo<T> & RightA<T>> T
selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightATypeClass());
}
}
ABImpl.java
package test;
public interface AB extends Combo<AB>, LeftA<AB>, RightB<AB> { }
AC.java
package test;
final class ABImpl extends BaseImpl<AB> implements AB {
@Override
public <T extends Combo<T> & LeftA<T>> T
selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftATypeClass());
}
@Override
public <T extends Combo<T> & RightB<T>> T
selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightBTypeClass());
}
}
ACImpl.java
package test;
public interface AC extends Combo<AC>, LeftA<AC>, RightC<AC> { }
BA.java
package test;
final class ACImpl extends BaseImpl<AC> implements AC {
@Override
public <T extends Combo<T> & LeftA<T>> T
selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getLeftATypeClass());
}
@Override
public <T extends Combo<T> & RightC<T>> T
selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
return selectRightTypeBase(selector, selector.getRightCTypeClass());
}
}
BAImpl.java
package test;
public interface BA extends Combo<BA>, LeftB<BA>, RightA<BA> { }
BB.java
package test;
final class BAImpl extends BaseImpl<BA> implements BA {
@Override
public <T extends Combo<T> & LeftB<T>> T
selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftBTypeClass());
}
@Override
public <T extends Combo<T> & RightA<T>> T
selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightATypeClass());
}
}
BBImpl.java
package test;
public interface BB extends Combo<BB>, LeftB<BB>, RightB<BB> { }
BC.java
package test;
final class BBImpl extends BaseImpl<BB> implements BB {
@Override
public <T extends Combo<T> & LeftB<T>> T
selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftBTypeClass());
}
@Override
public <T extends Combo<T> & RightB<T>> T
selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightBTypeClass());
}
}
BCImpl.java
package test;
public interface BC extends Combo<BC>, LeftB<BC>, RightC<BC> { }
CA.java
package test;
final class BCImpl extends BaseImpl<BC> implements BC {
@Override
public <T extends Combo<T> & LeftB<T>> T
selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftBTypeClass());
}
@Override
public <T extends Combo<T> & RightC<T>> T
selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
return selectLeftTypeBase(selector, selector.getRightCTypeClass());
}
}
CAImpl.java
package test;
public interface CA extends Combo<CA>, LeftC<CA>, RightA<CA> { }
CB.java
package test;
final class CAImpl extends BaseImpl<CA> implements CA {
@Override
public <T extends Combo<T> & LeftC<T>> T
selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftCTypeClass());
}
@Override
public <T extends Combo<T> & RightA<T>> T
selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightATypeClass());
}
}
CBImpl.java
package test;
public interface CB extends Combo<CB>, LeftC<CB>, RightB<CB> { }
CC.java
package test;
final class CBImpl extends BaseImpl<CB> implements CB {
@Override
public <T extends Combo<T> & LeftC<T>> T
selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftCTypeClass());
}
@Override
public <T extends Combo<T> & RightB<T>> T
selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
return selectLeftTypeBase(selector, selector.getRightBTypeClass());
}
}
CCImpl.java
package test;
public interface CC extends Combo<CC>, LeftC<CC>, RightC<CC> { }
所有这些代码都允许我进行以下操作:
package test;
final class CCImpl extends BaseImpl<CC> implements CC {
@Override
public <T extends Combo<T> & LeftC<T>> T
selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
return selectRightTypeBase(selector, selector.getLeftCTypeClass());
}
@Override
public <T extends Combo<T> & RightC<T>> T
selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
return selectLeftTypeBase(selector, selector.getRightCTypeClass());
}
}