在 Minecraft 中实现块功能时如何执行单一职责原则?

How to do Single Responsibility Principle when implementing Chunk functionality like in Minecraft?

我正在尝试为区块创建功能(就像我们在 Minecraft 中看到的由 16x16x256 块组成的区块)。

在实现单一职责原则的同时我应该如何去做?

功能包括加载、保存、创建网格和跟踪所有块。

我应该

  1. 创建一个包含许多 class 的块 class,每个块都具有其中一种功能,例如加载或保存。然后在 Chunk class 中启动 classes。 当这些 classes 需要 Chunk class 的功能时我该怎么办,这不会破坏 SRP 吗?

  2. 在块中创建所有功能class

所以,如果我们在这里谈论一般指针,那么可以从一些简单的事情开始。

  • 您的 Chunk class 应该只处理其主要职责 - 管理 Chunk.
  • 中包含的任何内容
  • 听起来您需要一个 ChunkGroup,可能会在 Chunk 上使用 Adapter 模式,它聚合了 Chunk 的 'network'。
  • 应该存在一些持久化 Chunk 对象的方法。这不是 Chunk 本身的责任,但可能涉及一个内部 class 允许将 Chunk 转换成可以(反)序列化的东西。

所以,我期待看到类似

的内容
interface Chunk {
    String doTheThing();
}

interface ChunkNetwork extends Chunk {
     add(Chunk chunk);
};

final class ChunkList implements ChunkNetwork {
    private List<Chunk> theChunks;

    add(Chunk chunk) {
        theChunks.add(chunk);
    }

    String doTheThing() {
        StringBuilder builder = new StringBuilder();
        for (Chunk chunk : theChunks) {
            builder.append(chunk.doTheThing());
        }
        return builder.toString();
    }
}

final class JsonChunk implements Chunk {
     @JsonProperty
     private final int someField;

     @Override
     public String doTheThing() {
         String.format("%d", someField);
     }

     @JsonCreator
     public JsonChunk(int fieldValue) {
         someField = fieldValue;
     }
 }

这里关于SRP的注意事项:

  • Chunk 接口仅包含与 Chunk 应该执行的核心功能相关的方法。
  • 适配器将创建 Chunk 个对象的 'network' 的功能提取到单独的 class 中。管理此类网络有不同的方法,您可能希望稍后更改它。您可以在不改变 Chunk 本身的工作方式的情况下这样做。
  • ChunkNetwork根据您的使用情况可能有不同的方法,这可能会告诉您如何选择实现接口,但关键是网络管理不在 Chunk 本身.
  • Chunk 对象如何在 XML 或 JSON(或任何磁盘上,文件中)中表示是与 API 的内容不同的问题Chunk 是。然而,对于像 Jackson 这样的库,我们通常可以不用为 marshalling/unmarshalling 定义单独的 class。但是,如果您的 Chunk 实现变得复杂,您可能需要这样做。

最终,SRP 表示任何个人 class 都应该有一个改变的理由。因此,您需要查看您的功能并查看它可能会发生变化的原因。典型的原因是:

  • 核心功能的变化。您的域可能需要额外/更改的功能。这相当于 Chunk 界面的变化。
  • 更改核心对象的排列方式以提供系统内的高级表示(也许您决定使用树结构表示 Chunk 的网络)。等同于 ChunkList class.
  • 的更改(或重新实现)
  • 持久性发生方式的变化。这可能是持久性库(例如 Jackson、JPA、JAXB 等)使用的注释的更改,或者它可能是代表 'Data Transfer Object'.
  • 的全新 class 结构

根据经验,如果您发现自己在描述 class 时使用了多个句子或使用了连词('and'、'but',还有逗号等标点符号)那么您可能会看到违反单一职责原则的情况。另一个经验法则是将这些句子/连词中的每一个都取出来,并尝试将它们隔离成一个 class。然后查看 class 是否违反了 SRP。冲洗并重复,直到没有任何东西违反 SRP。

听起来很简单,但就像国际象棋一样,学会需要几分钟,但要掌握则需要一生。