Let's say I have defined the following class:
public abstract class Event {
public DateTime Time { get; protected set; }
protected Event(DateTime time) {
Time = time;
}
}
What would you prefer between this:
public class AsleepEvent : Event {
public AsleepEvent(DateTime time) : base(time) { }
}
public class AwakeEvent : Event {
public AwakeEvent(DateTime time) : base(time开发者_高级运维) { }
}
and this:
public enum StateEventType {
NowAwake,
NowAsleep
}
public class StateEvent : Event {
protected StateEventType stateType;
public StateEvent(DateTime time, StateEventType stateType) : base(time) {
stateType = stateType;
}
}
and why? I am generally more inclined to the first option, but I can't explain why. Is it totally the same or are any advantages in using one instead of the other? Maybe with the first method its easier to add more "states", altough in this case I am 100% sure I will only want two states: now awake, and now asleep (they signal the moments when one awakes and one falls asleep).
I prefer the first. You can attach methods and behaviour to the classes, and move away from the switch/case pattern common with enums towards true polymorphism (and its benefits wrt. maintenance - adding new cases etc.).
Real OOPers don't use if
! Prefer polymorphism to conditionals.
Of course there could be situations where the enum
is the way to go (say, if you have a very, very large amount of states or you know that for the domain, it's very likely that all observers will be interested in all transitions), but in the general case, the first option is less complicated. Using the second approach, every listener must repeat the same piece of code:
if (theStateImInterestedIn == event.stateType){
/* actual code */
}
And every listener needs this, except for the listeners which react in the same way to all transitions! Code duplication! Aaaaargh! As we all know, repeated code causes bugs (hence the DRY principle), and so we can conclude that your gut feeling is correct - the first option (using two different classes) is the better, as every individual listener implementation will have less boiler plate.
Also; add an else
there and you've got interesting times ahead when you add a new state: Some listeners were interested in both types of events, and so assumed that the else
branch meant "the state I didn't check for in the if
". They now break because the else
clause covers >1 state.
It depends on what you're doing. If you are only managing states, then I would say stick with Enums (It's what I would do). If your states are more than just states, if instances of them will have behaviours, then go with classes.
Definetly the first way. Requirments always change. Also it much, much more cleaner the first way - you can use the base type everywhere and thus not exposing any of the derived ones - polymorphism in it's finest.
The disadvantage of the first one is you cannot change the state. If an object needs to go from awake state to asleep state you need to create a new object and copy the info etc. Shortly it won't work. Based on the names I think state changing behavior is needed this scenario.
Second option with enum will work but it will cause if/switch statements based on the state as other posters noted. The moment you repeat same type of switch/if statement (ifs are not the problem, the repeated ifs are the problem) it might be better to move to a polymorphic solution. In this case you would replace the enum with an interface or abstract class and have as many implementations as you want. The behavior that would go into the switch/if statements will go into methods in you concrete implementations
精彩评论