java - 如何从多个类继承状态?

标签 java inheritance design-patterns composite

我有一个类似复合的模式,其中树根、 Twig 和叶子有不同的功能。问题是根与分支和分支与叶之间存在共享状态。我正在寻找最干净的解决方案,以防止代码重复。

Diagram

根、分支和叶之间的功能都与同一组方法相关(尽管叶具有不同的签名)。

  • 可嵌入接口(interface)意味着该实现具有父级和一些可变属性。
  • Composite 具有Embeddable 子级,并提供抽象功能方法,其中RootBranch 有其单独的实现。
  • Root 是大多数功能的实际执行者。
  • 分支通常(但并非总是)将带有修改后的参数的信息传递给其父级。
  • Leaf 可以出现在根和分支上,并且具有较少的功能方法和较小的方法签名。将始终使用额外参数将其调用传递给其父级。它显式存储在创建和延迟加载的每个Composite中。

共享状态

  • 分支的共享状态在本例中由复合解决。
  • Embeddable 接口(interface)强制要求 BranchLeaf 提供其行为。

BranchLeaf 的实现问题是相同的,并且实现它会导致重复的代码。不可能使 Embeddable 成为一个抽象类,因为 Branch 已经扩展了 Composite

我正在寻找一种模式或通用解决方案,以便 Branch 可以同时与 EmbeddableComposite 共享状态。基本上是一个多重继承的解决方法。

实现

该设计实际上用于构建 3D block 环境。根在空间中是无限的,分支是在其父级空间中具有偏移量的子部分,叶代表相对于其父级偏移量的 1 个 block 。因此,根和分支的某些功能需要坐标作为参数,而叶则不需要这些,因为它已经在 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
}

最佳答案

目前尚不清楚具体的代码是重复的,但解决此类问题的常见方法是将状态和行为委托(delegate)给另一个类。

请记住,在可读性和维护此类代码的容易性之间总是需要权衡。现在请三思,您确实需要避免代码重复。

代码的简短示例

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;

关于java - 如何从多个类继承状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35074613/

相关文章:

c# - 如何在派生类中调用基类构造函数?

oop - 学习/实现设计模式(针对新手)

c++ - 单例实例声明为 GetInstance 方法的静态变量,它是线程安全的吗?

java - 如何在java中使用smack API以编程方式创建聊天室

java - netty如何确定读取何时完成?

java - 继承和覆盖同步方法

design-patterns - 具有函数式编程的企业模式

java - Spring 尝试使用 Jasypt 加密属性占位符解析属性占位符时抛出异常

java - 等待多线程时的最佳实践 - 时间、计数或其他?

java - 类似的子类