我使用以下技术来模拟混合(或特性)使用Java,并想知道这是合理的,或只是混淆未来的开发人员。此外,我相信一个好的命名方案是最好的文件,所以如果它将有助于改变命名,请提供建议。
/** A mixin interface which your class should implement */
public interface IsResizableMixin {
/**
* The implementation, which your class should
* instance and delegate calls to
*/
public static class IsResizableMixinImpl implements IsResizableMixin {
// A widget is e.g. a Swing Component, a GWT Widget, etc.
private Widget w;
pubic IsResizableMixinImpl(Widget w) {
this.w = w;
}
public void resizeTo(int width, int height);
/* for example */
w.setWidth(width);
w.setHeight(height);
w.getParent().redraw();
}
}
void resizeTo(int width, int height);
}然后是一个可调整大小的Widget的示例实现:
公共类Foo扩展Widget实现IsResizableMixin {私有IsResizableMixin混合;/* . */公共Foo() { super();this.mixin =新IsResizableMixinImpl(this);/* . */ /* . */ public mixin.resizeTo( int w,int h) { mixin.resizeTo(w,h);}}
一个更丰富的例子是一个Widget,它可以设置为“繁忙”,也就是说,覆盖一个旋转器和禁用的。
公共接口IsBusyMixin {公共类IsBusyMixinImpl实现IsBusyMixin {私有Widget w;私有布尔isBusy = false;pubic IsBusyMixinImpl(Widget ){ this.w .w= w;} public void toggleBusy();isBusy = !isBusy();如果(isBusy) { /*覆盖使用自旋器*/ } /* {/*删除自旋覆盖*/ }}空toggleBusy();}公共类Foo扩展Widget实现IsBusyMixin { //除此方法存在的事实以外,// Foo不知道可以切换到繁忙状态。公共空toggleBusy() { this.mixin.toggleBusy();}
这种办法的好处是:
Foo功能,我们会复制粘贴样板代码,但是如果发现了一个bug,我们就会忘记复制它的地方。这种方法的问题是:
getSize()方法,而IsResizeableMixin也可以声明一个getSize())。解决方案是给混合方法不同的名称。这只是一个简单的例子。将boolean放到实现类中也同样有效,但我试图将其从Foo中考虑进去。如果我们决定改变状态的存储方式,所有的IsBusyMixins都需要更新。
我错过了什么利弊?
请注意,Java 8's默认接口实现不涵盖此用例,因为mixins必须保持某种状态。
发布于 2015-04-19 19:26:12
即使您需要一些额外的状态,也总是有选择的:
您可以将类直接添加到类中,并在接口中为类提供方法,或者使用解决方案。
直接添加到类中,如下所示:
public interface IsBusyMixin {
boolean isBusy();
void dumbToggleBusy();
void overlayTheComponentWithASpinner(); // implement here or not
void removeTheSpinnerOverlay(); // implement here or not
public void toggleBusy();
dumbToggleBusy();
if (isBusy) {
overlayTheComponentWithASpinner();
} else {
removeTheSpinnerOverlay();
}
}
}
public class Foo extends Widget implements IsBusyMixin {
@Getter private boolean isBusy;
public void toggleBusy() {
isBusy = !isBusy();
}
}我想说,这总是有可能的。然而,它可能会变得比你的解决方案更丑陋。此外,所有接口方法都必须是公共的,这暴露了太多的内部状态。
因此,当事情变得更加复杂时,我不会滥用默认的方法,相反,我会使用您的方法。
然后,您可能会考虑使用一个默认的方法来公开mixin,或者另一个类似的方法
default void toggleBusy() {
this.mixin().toggleBusy();
}方法名称重叠,这就是多重继承不好的原因(例如,
Widget可能有一个getSize()方法,IsResizeableMixin也可以声明一个getSize())。解决方案是给混合方法不同的名称。
如果其中一个方法总是委托另一个方法,则可能应该保持名称相同。否则,无论你做什么,它都会让你感到困惑。
IsResizeableMixin的名字可能应该是Resizeable或ResizeableMixin。
发布于 2015-04-19 17:24:55
您的混合器的状态是this本身,因此没有附加状态,您可以使用默认方法。
public interface IsResizableMixin {
void setWidth(width);
void setHeight(height);
Redrawable setHeight(height);
default void redrawParent() {
getParent().redraw();
}
default void resizeTo(int width, int height) {
setWidth(width);
setHeight(height);
redrawParent();
}
}
public class Foo extends Widget implements IsResizeableMixin {
// This class has been intentionally left empty.
}从您的例子来看,我的Foo中没有遗漏什么。
https://codereview.stackexchange.com/questions/87352
复制相似问题