我的工作日志的活动,大约有60个不同的"类型"的事件。每个事件的股份约10性质,然后有类别的活动,分享各种额外的性质。

我怎么工作与这些事件不会取决于它们的类型或哪些类别的接口,它们的实施。

但它似乎是通向代码膨胀。我有很多冗余的子类方法,因为他们实现一些相同的接口。

它更适合用一个单一的事件类"类型"的财产并编写的逻辑,检查类型和维持某组织的类型(例如一个列表中的事件类型分类,第二列表中的b类,等等)?或是类设计更适合在这种情况下?

第一种方法:

public interface Category1 {}
public interface Category2 {}

public abstract class Event {
 private base properties...;
}

public class EventType1 extends Event implements Category1, Category2 {
 private extra properties ...;
}

public class EventType2 extends Event implements Category3, Category4 {
 private extra properties ...;
}

第二种方法:

public enum EventType {TYPE1, TYPE2, TYPE3, ...}
public class Event {
 private union of all possible properties;
 private EventType type;
}

我个人的意见是,这似乎是一个单一的事件的对象是什么是适当的,因为,如果我的想法是正确的,没有必要为使用继承代表模式,因为它是真的只的行为和我的条件是改变基于类型。

我需要有代码,不会这样的东西:

if(event instanceof Category1) {
  ...
}

这工作好在第一个方法,而不是实例,我们可以叫上的方法的事件和实行"相同的代码"在每个适当的子类。

但是,第二种方法是以更加简洁。然后我写这样的东西:

if(CATEGORY1_TYPES.contains(event.getEventType()) {
 ...
}

和我所有的"处理逻辑"可以组成一个单一类,并没有这是冗余之间传播的亚类。所以是这样一种情况下,虽然面向对象的出现更适当,它会更好,不是吗?

有帮助吗?

解决方案

这取决于每种类型的事件本身是否具有事件本身可以执行的不同行为。

您的Event对象是否需要每种类型的行为不同的方法?如果是这样,请使用继承。

如果没有,请使用枚举对事件类型进行分类。

其他提示

我会去的对象的每个事件类型的解决方案,但是我而不是集团通常使用组合的接受(可能抽象)类提供他们的 骨骼的实现.这极大地降低了代码膨胀产生的具有许多接口,但是,另一方面,增加的数量类。但是,如果使用正确和合理的,它会导致清洁的代码。

如果您决定扩展a的抽象基类,则继承可能会受到限制 特定的类别界面,因为您可能还需要实现另一个类别。

所以,这是一个建议的方法: 假设您需要为特定的Category接口方法实现相同的实现(无论事件如何),您可以为每个Category接口编写一个实现类。

所以你会:

public class Category1Impl implements Category1 {
    ...
}

public class Category2Impl implements Category2 {
    ...
}

然后,对于每个Event类,只需指定它实现的Category接口,并保留Category实现类的私有成员实例(因此,您使用组合,而不是继承)。对于每个Category接口方法,只需将方法调用转发给Category实现类。

由于我没有真正得到我正在寻找的答案,因此根据我不太理想的学习经验,我提供了自己最好的猜测。

事件本身实际上没有行为,它是具有行为的事件的处理者。事件只代表数据模型。

我重写了代码,只是将事件视为属性的对象数组,以便我可以使用Java的新变量参数和自动装箱功能。

通过这一改变,我能够删除大约100个巨大的代码类,并在一个类中的大约10行代码中完成大部分相同的逻辑。

经验教训:将OO范例应用于数据模型并不总是明智的。在处理大型可变域时,不要专注于通过OO提供完美的数据模型。 OO设计有时比模型更有益于控制器。不要先关注优化,因为通常10%的性能损失是可以接受的,并且可以通过其他方式重新获得。

基本上,我过度设计了这个问题。事实证明,这是一个适当的OO设计过度的情况,并将一个晚上的项目变成一个3个月的项目。当然,我必须以艰难的方式学习东西!

仅仅拥有大量的.java文件并不一定是坏事。如果您可以有意义地提取代表类的合同的少量(2-4左右)接口,然后打包所有实现,那么您提供的API可以非常干净,即使有60个实现。

我可能还建议使用一些委托或抽象类来引入通用功能。代理和/或抽象助手都应该是包私有或类私有的,在您公开的API之外不可用。

如果有相当多的混合和行为匹配,我会考虑使用其他对象的组合,然后让特定事件类型对象的构造函数创建这些对象,或者使用构建器来创建对象。

也许是这样的?

class EventType {

  protected EventPropertyHandler handler;

  public EventType(EventPropertyHandler h) {
     handler = h;
  }

  void handleEvent(map<String,String> properties) {
    handler.handle(properties);
  }
}

abstract class EventPropertyHandler {
   abstract void handle(map<String, String> properties);
}
class SomeHandler extends EventPropertyHandler {
   void handle(map<String, String> properties) {
      String value = properties.get("somekey");
      // do something with value..
   }
}

class EventBuilder {
   public static EventType buildSomeEventType() {
      // 
      EventType e = new EventType( new SomeHandler() );
   }
}

可能会有一些改进,但这可能会让你开始。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top