我正在构建一个应用程序,该应用程序会生成随机的音符序列,并将其作为音符显示给用户。这些序列可以根据几个参数生成,包括相同音高的密度和最大连续音符。
音乐序列由sequence
对象捕获,该对象的notes
属性是一个简单的音符字符串,例如"abcdaba"
。
我早期生成随机序列的尝试涉及一个SequenceGenerator
类,该类使用几种私有方法来编译随机序列。这对我来说似乎是一项服务。但是我试图遵守域驱动设计(Evans 2003)中表达的原则,即仅在必要时使用服务,并且更喜欢将行为与域对象相关联。
所以我的问题是:
是应该通过sequence
本身(例如generateRandom()
)上的公共方法来处理产生随机序列的工作,还是应该将其分开? >
我考虑了我的原始设计可能更像建造者或工厂模式而不是服务的可能性,但是创建随机序列的代码与创建带有提供的注释字符串的代码的代码有很大不同。 / p>
我对方法路由有一个担心,就是generateRandom()
作为sequence
上的方法会改变序列的 content ,但实际上并没有生成新的序列对象。这只是感觉不对,但我无法说明原因。
我仍在围绕一些OO核心设计原则,所以我们将不胜感激。
答案 0 :(得分:1)
是应该通过序列本身的公共方法(例如generateRandom())来处理生成随机序列的工作,还是应该将其分开?
我通常会发现,如果我以与对待“时间”或“ I / O”相同的方式对待“随机性”作为模型的输入,而不是作为模型的一个方面,则可以得到更简洁的设计本身。
如果您不考虑时间是输入值,请仔细考虑直到它成为输入值-这是一个重要的概念(John Carmack, 1998)。
在DDD的约束内,这可能意味着将“域服务”作为参数传递给您的方法,允许您的集合根据需要调用该服务,或者可能意味着在集合上具有一个方法,以便必要时,应用程序可以传递随机数。
因此,序列的任何创建都会涉及传递某种模式或种子,但是是否随机是在序列本身之外确定的?
是的。
答案 1 :(得分:0)
创建对象通常不被视为对象逻辑的一部分。
从技术上讲,这是另一回事。您可能会使用委派。例如:
public interface NoteSequence {
void play();
}
public final class LettersNoteSequence implements NoteSequence {
public LettersNoteSequence(String letters) {
...
}
...
}
public final class RandomNoteSequence implements NoteSequence {
...
@Override
public void play() {
new LetterNoteSequence(generateRandomLetters()).play();
}
}
通过这种方式,您不必拥有“服务”或“工厂”,但这只是一种选择,可能会或可能不会适合您的用例。