如何从多个 类 继承状态?
How to inherit state from multiple classes?
我有一个类似复合的模式,其中树、枝和叶的根具有不同的功能。问题在于 Root with Branch 和 Branch with Leaf 之间存在共享状态。我正在寻找防止代码重复的最干净的解决方案。
根、分支和叶之间的功能都与同一组方法相关(尽管叶具有不同的签名)。
- Embeddable 接口暗示该实现具有父级和一些可变属性。
- Composite 有 Embeddable 个子级,并为 Root 和 Branch 有各自的实现。
- Root 是大多数功能的实际执行者。
- Branch 最常(但并非总是)将信息传递给其父级并修改参数。
- Leaf 可以同时出现在根和分支上,并且具有较少的功能方法和较小的方法签名。将始终使用额外参数将其调用传递给其父级。它显式存储在每个 Composite 中,在那里创建并延迟加载。
共享状态
- Root 和 Branch 的共享状态在这种情况下由 Composite 解决。
- Embeddable 接口强制 Branch 和 Leaf 提供其行为。
Branch 和 Leaf 的实施问题相同,实施它会导致重复代码。使 Embeddable 成为抽象 class 是不可能的,因为 Branch 已经扩展了 Composite.
我正在寻找一种模式或通用解决方案,以便 Branch 可以与 Embeddable 和 Composite 共享状态同时。基本上是多重继承解决方法。
实施
这个设计在实践中用于构建 3D 块环境。根在 space 中是无限的,分支是在其父级的 space 中具有偏移量的子部分,而叶代表相对于其父级偏移量的 1 个块。因此,根和分支的一些功能需要坐标作为参数,而叶不需要这些,因为它已经在 1 坐标。
public abstract class Container{
private List<Embeddable> children;
private WeakHashMap<Integer, Leaf> leafs;
public abstract boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy setBlockStrategy);
public abstract void tick();
public abstract void activate(short x, short y, short z);
protected final Leaf getLeaf(short x, short y, short z) { ... }
protected void addChild(short x, short y, short z, Embeddable child) { ... }
}
public interface Embeddable {
void setParent(Container parent, short x, short y, short z);
void clearParent();
Container getParent();
}
public class Root extends Composite {
private RootSpecificObject rootSpecificParameter;
public boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy setBlockStrategy) {
controller.doStuff();
}
public void tick() {
controller.doStuff();
}
public void activate(short x, short y, short z) {
controller.doStuff();
}
}
public class Branch extends Composite implements Embeddable {
private BranchSpecificObject branchSpecificParameter;
// Duplicate code
private short xOffset, yOffset, zOffset;
private Container parent;
public boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy sbs) {
parent.setBlock(x + xOffset, y + yOffset, z + zOffset, id, data, sbs);
}
public void tick() {
controller.doStuff(xOffset, yOffset, zOffset, ...);
}
public void activate(short x, short y, short z) {
parent.activate(x + xOffset, y + yOffset, z + zOffset);
}
// Duplicate Embeddable implementation
}
public class Leaf implements Embeddable {
private byte id, data;
// Duplicate code
private short xOffset, yOffset, zOffset;
private Container parent;
public boolean setBlock(byte id, byte data, SetBlockStrategy sbs) {
return parent.setBlock(xOffset, yOffset, zOffset, id, data, sbs);
}
public void activate(short x, short y, short z) {
parent.activate(xOffset, yOffset, zOffset, id, data, sbs);
}
// Duplicate Embeddable implementation
}
不清楚具体重复了哪些代码,但解决此类问题的常见方法是将状态和行为委托给另一个 class。
请记住,在可读性和易于维护此类代码之间始终存在权衡。现在请三思,您确实需要避免代码重复。
代码的简短示例
public class Branch extends Composite implements Embeddable {
EmbeddableDelegate delegate;
}
public class Leaf implements Embeddable {
EmbeddableDelegate delegate;
}
public class EmbeddableDelegate [implements Embeddable] {
private short xOffset, yOffset, zOffset;
private Container parent;
我有一个类似复合的模式,其中树、枝和叶的根具有不同的功能。问题在于 Root with Branch 和 Branch with Leaf 之间存在共享状态。我正在寻找防止代码重复的最干净的解决方案。
根、分支和叶之间的功能都与同一组方法相关(尽管叶具有不同的签名)。
- Embeddable 接口暗示该实现具有父级和一些可变属性。
- Composite 有 Embeddable 个子级,并为 Root 和 Branch 有各自的实现。
- Root 是大多数功能的实际执行者。
- Branch 最常(但并非总是)将信息传递给其父级并修改参数。
- Leaf 可以同时出现在根和分支上,并且具有较少的功能方法和较小的方法签名。将始终使用额外参数将其调用传递给其父级。它显式存储在每个 Composite 中,在那里创建并延迟加载。
共享状态
- Root 和 Branch 的共享状态在这种情况下由 Composite 解决。
- Embeddable 接口强制 Branch 和 Leaf 提供其行为。
Branch 和 Leaf 的实施问题相同,实施它会导致重复代码。使 Embeddable 成为抽象 class 是不可能的,因为 Branch 已经扩展了 Composite.
我正在寻找一种模式或通用解决方案,以便 Branch 可以与 Embeddable 和 Composite 共享状态同时。基本上是多重继承解决方法。
实施
这个设计在实践中用于构建 3D 块环境。根在 space 中是无限的,分支是在其父级的 space 中具有偏移量的子部分,而叶代表相对于其父级偏移量的 1 个块。因此,根和分支的一些功能需要坐标作为参数,而叶不需要这些,因为它已经在 1 坐标。
public abstract class Container{
private List<Embeddable> children;
private WeakHashMap<Integer, Leaf> leafs;
public abstract boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy setBlockStrategy);
public abstract void tick();
public abstract void activate(short x, short y, short z);
protected final Leaf getLeaf(short x, short y, short z) { ... }
protected void addChild(short x, short y, short z, Embeddable child) { ... }
}
public interface Embeddable {
void setParent(Container parent, short x, short y, short z);
void clearParent();
Container getParent();
}
public class Root extends Composite {
private RootSpecificObject rootSpecificParameter;
public boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy setBlockStrategy) {
controller.doStuff();
}
public void tick() {
controller.doStuff();
}
public void activate(short x, short y, short z) {
controller.doStuff();
}
}
public class Branch extends Composite implements Embeddable {
private BranchSpecificObject branchSpecificParameter;
// Duplicate code
private short xOffset, yOffset, zOffset;
private Container parent;
public boolean setBlock(short x, short y, short z, byte id, byte data, SetBlockStrategy sbs) {
parent.setBlock(x + xOffset, y + yOffset, z + zOffset, id, data, sbs);
}
public void tick() {
controller.doStuff(xOffset, yOffset, zOffset, ...);
}
public void activate(short x, short y, short z) {
parent.activate(x + xOffset, y + yOffset, z + zOffset);
}
// Duplicate Embeddable implementation
}
public class Leaf implements Embeddable {
private byte id, data;
// Duplicate code
private short xOffset, yOffset, zOffset;
private Container parent;
public boolean setBlock(byte id, byte data, SetBlockStrategy sbs) {
return parent.setBlock(xOffset, yOffset, zOffset, id, data, sbs);
}
public void activate(short x, short y, short z) {
parent.activate(xOffset, yOffset, zOffset, id, data, sbs);
}
// Duplicate Embeddable implementation
}
不清楚具体重复了哪些代码,但解决此类问题的常见方法是将状态和行为委托给另一个 class。
请记住,在可读性和易于维护此类代码之间始终存在权衡。现在请三思,您确实需要避免代码重复。
代码的简短示例
public class Branch extends Composite implements Embeddable {
EmbeddableDelegate delegate;
}
public class Leaf implements Embeddable {
EmbeddableDelegate delegate;
}
public class EmbeddableDelegate [implements Embeddable] {
private short xOffset, yOffset, zOffset;
private Container parent;