c# - How to write a clear and elegant code for a strategy pattern based application? -
i writing application compose musical freizes, little worried structure of classes , interfaces within code. here there signatures of classes wrote:
interface iguidoformattable class note : iguidoformattable, icloneable class pause : iguidoformattable, icloneable class chord : list<note>, iguidoformattable, icloneable class key : iguidoformattable, icloneable class tempo : iguidoformattable, icloneable class meter : iguidoformattable, icloneable class fretpiece : list<iguidoformattable>, icloneable class fret : list<fretpiece>
fretpiece represents muscial phrase, piece of complete freize. exposes properties key, tempo , meter, homonym types. more phrases put create freize, respresented fret class. every element within single phrase must formattable in accordance guido standard notation, hence has implement iguidoformattable interface. in namespace, mutation classes defined , inherit 1 of 2 abstract classes:
class fretmutation class lambdafretmutation : fretmutation
finally, there exists class called fretmutationgenerator has task of applying selected mutations music theme , output entire freize instance of fret class.
fretpiece must able contain several different elements (notes, pauses , chords in case), nonetheless must satisfy 2 constraints: have formattable guido notation , therefore transformed meaningful strings; have cloneable. in code now, every class implements icloneable, syntax , semantics of current code not grant members of collection cloneable. need find way express both constraint without applying inheritance iguidoformattable , preferably without defining clone method in iguidoformattable interface.
second, , important, problem. fretmutation defines abstract method, "apply", has overridden in every derived class. therefore, mutation class defines own version of method, has following signature:
fretpiece apply(fretpiece originaltheme)
it accepts input fretpiece , outputs copy of object, mutated according other parameters specified members of class. think implementation of strategy pattern. however, becase of fact method creats copy of input, means argument (and therefore members) must cloneable. in addition, fretpiece declared list of iguidoformattable, every mutation class behaves differently others , may act on notes, pauses or chord, accordingly: means need check every element's type, , write different code each type "a lot" (indeed, 3 @ most) if statements. , seems me little object oriented.
how can arrange classes , interface in way become more object oriented , less dependent on assumptions , type-checking?
i need find way express both constraint without applying inheritance iguidoformattable , preferably without defining clone method in iguidoformattable interface
what third option?
public interface icloneableandguidoformattable : iguidoformattable, icloneable { }
then fretpiece list of icloneableandguidoformattable
if not that, try such construct:
public interface icloneable<t> { t clone(); } public class fretpiece : ienumerable<iformattable>, icloneable<fretpiece> { private list<iformattable> items = new list<iformattable>(); public void add<t>(t value) t : iformattable, icloneable<iformattable> { items.add(value); } public ienumerator<iformattable> getenumerator() { items.getenumerator(); } ienumerator ienumerable.getenumerator() { return getenumerator(); } public fretpiece clone() { return new fretpiece { items = new list<iformattable>( items.cast<icloneable<iformattable>>().select(c=>c.clone())) }; } }
and somewhere else e.g. on mutator:
public t apply<t>(t fretpiece) t : ienumerable<iformattable>, icloneable<t> ( ...)
this ensure can add items implementing both interfaces. enumeration assumes iformattables returned. allow inside cast safely cast icloneable since must have passed type constraint on "add". can see implementation of clone. though have cast there safe unless fiddles items
based on reflection ;)
Comments
Post a Comment