"集装箱"上课,好或坏的做法,为什么?

时间:2014-12-01 13:07:14

标签: java

我很好奇哪个是更好的做法和背后的推理,对于这个例子,我将使用一个社交应用程序,其中包含一个朋友'并且忽略'列出一些基于它们的自定义逻辑,(用于直接发送消息等)

哪种做法更好,为什么?

场景1

class user {
    List<> friends;
    List<> ignores;
    ...
    logical methods here
}

场景2

class User {
     Social social;
     ...
}
class Social {
    List<> friends;
    List<> ignores;
    ...
    logical methods here
}

我已经看过很多应用程序中使用的两个场景,我很好奇哪个是&#34;正确&#34;在java中进行布局的方法,这些方法有

等方法
#addFriend(User user)
    check ignore
    check valid user
    check other info
    add to list
end

   #getFriend(int id)
        find friend by id
        check online status
   return friend

好像有一个社交&#39;上课可能是一种更清洁的方法,它是否真的遵循良好做法?似乎它只是为了更清晰的代码而使用更多的内存/用户。

6 个答案:

答案 0 :(得分:2)

在大多数情况下,您拥有Social这样的结构的原因是它们代表了应用程序中不同实体所需的逻辑数据和操作集。

如果User以外的任何内容都没有这些属性和操作,则与User分开进行操作是没有意义的。但是您可以将其单独设计,以备将来使用(例如,如果您希望以后能够扩展它,并且您认为将有其他需要Social功能的实体)。

从面向对象的角度来看,这意味着Social是一种类型。然后你必须问自己,你的User 是__ Social还是User has_a Social 。说用户有一个&#34;社交子系统&#34;是否有意义?或者是用户&#34;社交对象&#34;?如果正确的关系是 is_a ,那么User应该扩展 Social。如果没有,它应该有Social成员,如您所描述的那样。

但是,在Java中,由于您无法实现多个继承,因此有时您的类型可能会继承多种类型,您必须决定将哪些类型扩展。很多时候,您通过拥有应该是&#34;第二个父类&#34;的成员来模拟实现的多重继承,声明您的类中的所有方法,并将它们委托给该成员。

所以一般指导方针或多或少:

  • 如果在您的应用程序的域中,唯一有friendsignores及其操作有意义的类是User,并且没有其他可想到的实体会永远需要它们,然后直接在User
  • 中实施它们
  • 如果其他实体可能需要类似的功能,并且并非所有这些功能都延伸User,您可以将此功能视为一个实体或类本身,然后您应该拥有每个具有 is_a 与此实体的关系扩展了它。
  • 如果Java的多重继承限制不允许直接扩展,因为对于扩展其他类更有意义,你应该嵌入一个对象并委托操作。

Social实体与User分开可能有其他实际原因,尽管User是唯一使用它们的类。例如,如果您有几种不同的可能实现&#34; social&#34;行为,您可能希望能够使用各种Social子类作为&#34;插件&#34;在User内,而不是继承User

答案 1 :(得分:1)

不要那么早地担心记忆。寻找可读/更清晰的代码。过早优化是万恶之源。

答案 2 :(得分:1)

这实际上是基于程序的逻辑。但是考虑到不必要地增加课程数量并不是一种好习惯。

在您的示例中,如果User类仅包含Social字段,并且您只是将所有方法调用委托给Social类,那么请使用方案一。

另一方面,如果User类有更多字段,如名称,加入日期......那么为UserInfo等字段创建单独的类会更好,以便更好地构建程序并提高代码可读性。

答案 3 :(得分:0)

现在主要关注的不是类结构的内存或性能成本。

更重要的是可读性和干净的代码,以及以最简单有效的方式在域中持久保存域类的可能性。

后者包含composition or aggregation关注点,该问题针对不同的数据库。

答案 4 :(得分:0)

你应该关心设计方面的问题,你将拥有可维护,可扩展和可读的代码。

现在以你的例子为例,我发现第二种情况与SRP(单一责任原则)之后的情况一样好

不要担心这里的记忆,因为它不会在这里产生差异。

答案 5 :(得分:0)

所以你想做点什么:

for(Connection connection : userSocialConnections ){
sendMessageTo(connection);
}

如果是这样,那么方法sendMessageTo将需要接受连接(朋友或忽略,基本上是用户),并且可能如果忽略runtype连接(或已阻止用户),则sendMessageTo将返回而不以多态方式发送消息。这需要在java中,IgnoredPeople和Friends是被称为Connection的东西的子类型(或者你喜欢的人或任何东西;实际上,连接也是用户 - 当前或潜在的,不是吗?)。对我而言,这种方法似乎更像是在问题领域进行思考。在用户内部或社交内部用户中存储两个列表并不重要,只要他们(被忽略和朋友)都有一个共同的界面。

我会问,对于用户的朋友或被忽略的列表,所有其他场景都可以。是否需要懒散加载或单独存放。