0

自从我接触面向对象编程以来已经有很长一段时间了,所以我有点生疏了,希望你的洞察力。

给定一个类,例如 CDPlayer,它包括字段 numberOfTracks 和 currentTrack 以及方法 getCurrentTrack 和 setCurrentTrack,我应该把将当前轨道设置为随机轨道的功能放在哪里?在此类内部的 setRandomTrack 等方法中,还是在此类外部的应用程序代码中(例如 player1.setCurrentTrack(randomnumbergeneratingcode ))?

这些方法的优缺点是什么?哪个更易于使用、更改和维护?上面的例子非常简单,但是当我希望随机数生成灵活时,事情会如何改变——一个 CDPlayer 实例使用正态分布进行随机化,另一个使用平面分布,另一个使用由某些定义的分布一组数字,等等。

编辑

感谢到目前为止的三个回复。

考虑对 op 的扩展......经过大量编码后,很明显,在许多情况下,我们不得不在应用程序代码中将当前轨道更改为之前的轨道 3,但仅限于星期四(这可能具有非平凡的条件逻辑才能正常工作)。很明显,在整个开发过程中,我们将不得不做很多次。此功能不会面向用户(就用户而言它是无用的),它只是出于某种原因我们需要在代码中多次设置的东西。

我们是否在类中创建了一个 setThreeTracksBeforeOnThursdays 方法并打破了该类所具有的 CD 播放器的紧密代表性模型,还是我们绝对坚持紧密的代表性模型并将此功能保留在应用程序代码中,尽管它增加了痛苦应用代码?设计应该摇动开发人员还是开发人员应该摇动设计?

4

4 回答 4

0

好吧,除了代码更具可读性之外,代码的位置并没有真正的好处。

但在某些情况下,将代码放入类中可能会减少冗余,这完全取决于语言。例如:

类中的 C# 代码:

private Random random = new Random();

public void setRandomTrack()
{
    setCurrentTrack(random.NextInt());
}

类外的 C# 代码:

Random random = new Random();
CDPlayer player = new CDPlayer()
player.setCurrentTrack(random.NextInt());

外部的代码必须在类外部创建一个随机生成器来生成一个随机整数,如果它对您调用它的类不可见,您可能必须多次创建随机生成器。

于 2013-09-26T06:18:56.073 回答
0

让我们尝试实现这个功能。播放随机曲目有什么要求?

  • 它应该是随机的(当然),
  • 它应该不是当前曲目(如果还有其他曲目要播放,没有人愿意连续听五次当前曲目)
  • 您应该从播放器中存在的曲目中选择曲目(曲目编号不应超过曲目数量)。

我将使用 C#:

Random random = new Random();
CDPlayer player = new CDPlayer();
// creates list of track indexes, e.g. { 1, 2, 3, 4, 5, 6, 7 }
var tracksNotPlayed = Enumerable.Range(0, player.NumberOfTracks - 1).ToList();

if(tracksNotPlayed.Count == 0)
   // initialize list again, or stop

int index = random.Next(tracksNotPlayed.Count);
int nextTrack = tracksNotPlayed[index];
player.SetCurrentTrack(nextTrack);
tracksNotPlayed.Remove(nextTrack);

对我来说,这看起来像是功能羡慕- 其他一些类使用来自播放器的数据来实现此功能。不好。让我们进行一些重构 - 将所有这些东西移到播放器中:

public void PlayRandomTrack() // Shuffle
{
    if(tracksNotPlayed.Count == 0)
       tracksNotPlayed = Enumerable.Range(0, numberOfTracks - 1).ToList();

    int index = random.Next(tracksNotPlayed.Count);
    int nextTrack = tracksNotPlayed[index];
    SetCurrentTrack(nextTrack);
    tracksNotPlayed.Remove(nextTrack);         
}

它看起来更好,并且更容易在外面使用:

CDPlayer player = new CDPlayer();
player.PlayRandomTrack();

此外,如果您正在实现诸如 Winamp 之类的东西(它有两种模式 - 随机播放和顺序播放,当它一首自动播放歌曲时)然后考虑将此逻辑移动到一些策略中(或者它应该是Iterator?),它将有两个实现 - 顺序和随机播放,并且对播放器一无所知 - 它的责任是在某个范围内选择数字(应该传递被枚举的轨道或集合的数量):

public abstract class CollectionIterator<T>
{        
    public CollectionIterator(IEnumerable<T> source)
    {
       // save source
    }

    abstract int GetNextItemIndex();
}

播放器将使用此迭代器/策略来播放下一个项目:

public void PlayTrack()
{
    SetCurrentTrack(iterator.GetNextItemIndex());
}

所以,我们在这里有明确的职责分离——客户端使用播放器来听音乐,播放器知道如何播放音乐,迭代器知道如何从集合中选择下一个项目。ThursdaysCollectionIterator如果您想在星期四创建一些其他序列,您可以创建。这将使您的播放器和客户端代码保持不变。

于 2013-09-26T07:04:14.067 回答
0

将其放入 CDPlayer 的好处在于,它将是一个单一的方法调用,并且该函数非常典型地用于 CD 播放器,因此它“感觉不错”。

将它放入您的应用程序的一个缺点是它需要两次调用,一次用于获取轨道数以便您可以生成随机数,一次用于设置它。

将它放入 CDPlayer 的一个缺点是该类需要了解随机数。在这种特殊情况下,使用标准库非常简单,但如果这是一些顶级安全 CIA CD 播放器,则可能会出现问题。(刚刚注意到你编辑了你的帖子以暗示类似的事情)

我会把代码放在 CDPlayer 中,(并添加一个方法来更改随机数生成器,这个花哨的术语是依赖注入)但这篇文章希望能给你一些利弊。

于 2013-09-26T06:17:30.957 回答
0
  • 如果它是所有 CD 播放器都有的功能,那么它应该在 CDPlayer 类中。
  • 如果是少数CD播放器才有的功能,那么你应该继承CDPlayer类,并将该功能放在子类中。
  • 如果它是 CD 播放器没有的功能,那么就没有理由将它包含在类中。CDPlayer让全班知道选择随机曲目是否有意义?如果没有,它应该在类外实现。
于 2013-09-26T06:26:49.590 回答