类层次结构爆炸

时间:2020-03-05 07:50:11

标签: java inheritance design-patterns decorator

我正在尝试为我的类层次结构找到解决方案,我认为它会爆炸 假设我有一个这样的事件接口

public interface Event  {
String getId();

String getType();

String getName();

String getDescription();

Date getDate();

JsonElement getRaw();
}

public  class BasicEvent implements Event {
protected String        eventId;
protected String        eventType;
protected String        eventDescription;
protected String        eventName;
protected Date        time;
protected JsonElement   raw;

public BasicEvent(String eventId, String eventType, String eventDescription, String eventName, Date time,
                  JsonElement raw) {
    this.eventId = eventId;
    this.eventType = eventType;
    this.eventDescription = eventDescription;
    this.eventName = eventName;
    this.time = time;
    this.raw = raw;
}

public BasicEvent(String eventId, String eventType, Date time, JsonElement raw) {
    this(eventId, eventType, null, eventId, time, raw);
}

public BasicEvent(String eventId, String eventType, Date time, String eventName, String eventDescription) {
    this(eventId, eventType, eventDescription, eventName, time, null);
}

@Override
public String getId() {
    return this.eventId;
}

@Override
public String getType() {
    return this.eventType;
}

@Override
public String getName() {
    return this.eventName;
}

@Override
public String getDescription() {
    return this.eventDescription;
}

@Override
public Date getDate() {
    return this.time;
}


@Override
public JsonElement getRaw() {
    return raw;
}

public Map<String, Object> getData() {
    return new Gson().fromJson(raw, Map.class);
}

@Override
public String toString() {
    return "BasicEvent{" + "eventId=" + eventId + ", eventType=" + eventType + ", time=" + time + ", raw=" + raw
        + '}';
}
}

可以从系统,设备或区域触发事件,因此使用继承,我可以添加3个类

public class ZoneEvent extends  BasicEvent {
private Long zoneId;

public ZoneEvent(BasicEvent event, Long zoneId) {
    super(event);
    this.zoneId = zoneId;
}

public Long getZoneId() {
    return zoneId;
}

public void setZoneId(Long zoneId) {
    this.zoneId = zoneId;
}
}


public class DeviceEvent extends BasicEvent {
private Long deviceId;
private String driverId;
private String deviceType;

public DeviceEvent(BasicEvent event, Long id, String driverId, String deviceType) {
    super(event);
    this.deviceId = id;
    this.deviceType = deviceType;
    this.driverId = driverId;

}

public String getDriverId() {
    return driverId;
}

public void setDriverId(String driverId) {
    this.driverId = driverId;
}

public void setDeviceId(DeviceId id) {
    this.deviceId = id;
}

public void setDeviceType(String deviceType) {
    this.deviceType = deviceType;
}

public DeviceId getDeviceId() {
    return deviceId;
}

public String getDeviceType() {
    return deviceType;
}
}


public class SystemEvent extends  BasicEvent {
private Long systemId;
public SystemEvent(BasicEvent event, Long systemId) {
    super(event);
    this.systemId=systemId;
}

public Long getSystemId() {
    return systemId;
}

public void setSystemId(Long systemId) {
    this.systemId = systemId;
}
}

现在,一个事件可以是这3个类的组合,一个事件可以包含ZoneId和deviceId或deviceId和SystemId,并且我的类层次结构将爆炸。这个设计有什么解决方案吗?并使用装饰器可以解决这个问题之王?

1 个答案:

答案 0 :(得分:1)

好的,因此您在考虑基于属性而不是其功能来分离类方面有更多思考。这种情况在oop周围很常见,但我认为这是错误的。

我认为您应该做的是抛弃充满吸气剂的接口,仅使用一种方法创建接口。考虑一下您需要事件对象做什么?也许通过电线发送?那么该方法是send()。也许另一个人负责发送它?那么您可能需要将事件的内容打印到流中,因此该方法将类似于print(OutputStream out)。

由于您提到一个事件可以是这3个事件的任意组合,所以我想说您重新考虑需要3个单独的类。您似乎只需要一个接受不同属性(例如在Map或其他内容中)的对象。如果您真的需要将它们分开,因为它们每个都具有不同的功能,但是在某一时刻您需要将它们的信息组合在一起,那么我建议您在此处说明打印机模式: https://www.yegor256.com/2016/04/05/printers-instead-of-getters.html 每个事件实现都有一个方法打印,该方法将自己的内容写入您定义的构建器类。然后,根据需要使用该构建器类。

Sandi Metz也有一个相关的演讲,涉及您提到的类层次结构问题。 https://youtu.be/OMPfEXIlTVE强烈推荐。

希望有帮助!