Reputation: 3
I'm trying to find a solution to my classes hierarchies which i think it will explode Say that i have an Event interface like this
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
+ '}';
}
}
An event can be triggred from a system , from a device or from a zone so using inheritance i add 3 classes
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;
}
}
Now an event can be a combination from these 3 classes an event can contain ZoneId and deviceId or deviceId and SystemId and my classes hierarchies will explode . is there any solution to this design? and using decorator can solve this king of problem?
Upvotes: 0
Views: 460
Reputation: 439
Ok, so you are thinking more in terms of separating classes based on attributes instead of their functionality. This is very common to see around oop, but I think it is wrong.
What I think you should do is ditch the interface full of getters and create one with only one method. Think on what do you need the event object for? maybe send it over the wire? then the method is send(). Maybe another guy is in charge of sending it? then you may need to print the contents of the event to a stream so the method would be something like print(OutputStream out).
Since you mentioned that an event can be any combination of those 3, I would say that you reconsider needing 3 separate classes. You seem to only need one that accepts different properties like in a Map or something. If you truly need to separate them because each has a different functionality but at one point you need to combine the info of them all, then I would suggest the printer pattern explained here: https://www.yegor256.com/2016/04/05/printers-instead-of-getters.html Each event implementation would have a method print that writes their own content into a builder class that you define. Then you use that builder class as you need.
There is also a related talk from Sandi Metz that touches the class hierarchy problem that you mentioned. https://youtu.be/OMPfEXIlTVE Highly recommended.
Hope it helps!
Upvotes: 1