I'm currently learning the SOLID (OO Design) and something bugs me: the dependency inversion principle, according to which the upper policy layer should be able to comply with a lower one's interface, made me wonder; where do event's fit in?
For example (taken from "Agile Principles, Patterns, and Practices in C#"):
Here, when the button is turned on/off, it calls turnOn/turnOff on the ButtonServer it would have some reference to.
Now if several objects were to depend on one single button, in order for this to work (imo), the button would have to store a list of ButtonServer's and then call on each one's turnOn/turnOff.
This looks to me like reinventing what event already does.
Now if that button were to have a new state, sleep, we'd have to create a new interface ButtonServerSleep (or some other name) and we'd have to store a new different list of each ButtonServerSleep which would be depending on the button*. And will just end up writing the same kind of code for looping through ButtonServer and call turnOn/turnOff than for looping through ButtonServerSleep and call sleep, the kind of code to which event's were made to avoid.
* if this would break the SRP, tell me.
The example with buttons and lamps is quite hard to follow, but I'll try:
public class Button
{
IButtonServer _buttonServer;
private bool _amIOn;
public Button(IButtonServer buttonServer)
{
_buttonServer = buttonServer;
}
void Poll()
{
_amIOn = !_amIOn;
if(_amIOn) _buttonServer.TurnOn(); else _buttonServer.TurnOff();
}
}
interface ITurnOnOffableDevice
{
void TurnOn();
void TurnOff();
}
interface IButtonServer : ITurnOnOffableDevice
{
void RegisterDevice(ITurnOnOffableDevice l);
}
public Lamp : ITurnOffableDevice
{
public Lamp(IButtonServer buttonServer)
{
buttonServer.RegisterDevice(this);
}
public void TurnOn()
{
Shine();
}
public void TurnOff()
{
Darken();
}
}
public MeatTriturator : ITurnOffableDevice
{
public MeatTriturator(IButtonServer buttonServer)
{
buttonServer.RegisterDevice(this);
}
public void TurnOn()
{
Triturate();
}
public void TurnOff()
{
ShutItDown();
}
}
Now, on some DLL which doesn't know about lamps, or meat triturators, you have this:
public ButtonServer : IButtonServer
{
private List<ITurnOnOffableDevice> _devices = new List<ITurnOnOffAbleDevice>();
public void RegisterDevice(ITurnOnOffAbleDevice l)
{
_devices.Add(l);
}
public void TurnOn()
{
foreach(var l in _devices) { l.TurnOn(); }
}
public void TurnOff()
{
foreach(var l in _devices) { l.TurnOff(); }
}
}
Then you create everything:
public static IButtonServer MyLampAndTrituratorButtonServer;
static void Prepare()
{
DependencyInject.ForType<IButtonServer>.Create<ButtonServer>();
}
static void Main()
{
Prepare();
MyLampAndTrituratorButtonServer = DependencyInject.CreateObject<IButtonServer>();
// The MyLampAndTrituratorButtonServer could be injected directly in the
// constructor of these objects, but for clarity I've left the normal
// object declaration
// this button will turn on lamps and meat triturators
var button = new Button(MyLampAndTrituratorButtonServer);
// these lamp and meat tritutator will be turned on/off by
// the buttons in that server
var lamp = new Lamp(MyLampAndTrituratorButtonServer);
var meatTriturator = new MeatTriturator(MyLampAndTrituratorButtonServer);
}
Then somewhere else, deep inside your program, you have the need to create a new button that lights up that lamp and meat triturator, you'd just do:
var button = new Button(MyLampAndTrituratorButtonServer);
No reference whatsoever to the actual lamp, or the meat triturator.
(Or better yet: create the button while injecting the IButtonServer dependency on the constructor parameter (this would depend on your dependency injector, so I'm not giving code), but then you'd neither need the reference to MyLampAndTrituratorButtonServer)
With this, you have decoupled your buttons from your lamps or meat triturators. The action of turning off and on is done by the button server, which as you can
see is injected, so it could be anything (anything that implements IButtonServer).
So you have delegated the responsibility of turning on and off the devices to a single dependency.
Again, in the "real world", buttons tend to do just one thing, and lamps only turn off and on, and this is dubious to change in the future... but this is an example of delegating the responsibility to a single point.
But let's take it a bit further... imagine your requirements have changed, and the buttons which turn on/off lamps and meat triturators (and only those, not all buttons), need to have a security measure. Whenever they are turned on, they need to auto-shutdown in 30 seconds.
With your "events based approach", you would need to derive one object from "button" (i.e., ButtonThatTurnsOffAt30secs : Button) and change -everywhere- where a lamp or meat triturator is created, then recompile.
With the isolated dependency, you'd just rewrite your buttonserver:
public ButtonServerThatTurnsOffAt30seconds : IButtonServer
{
private List<ITurnOnOffableDevice> _devices = new List<ITurnOnOffAbleDevice>();
public void RegisterDevice(ITurnOnOffAbleDevice l)
{
_devices.Add(l);
}
public void TurnOn()
{
foreach(var l in _devices) { l.TurnOn(); new Timer(30, () => { TurnOff(); } }
}
public void TurnOff()
{
foreach(var l in _devices) { l.TurnOff(); }
}
}
And change your dependency injection:
DependencyInject.ForType<IButtonServer>.Create<ButtonServerThatTurnsOffAt30seconds>();
If you have separated your project right, you wouldn't even need to recompile the whole application, just a single DLL change (or two if you have the dependency injector bootstrap on a different one) and voilá, now all your lamps and meat triturators turn off at 30 seconds.
Again, this is not the best example, and it made making an example hard, but I hope you can follow.
As a disclaimer: I'm trying to make a value on dependency isolation, not aiming to explain SOLID principles or any pattern, since you seem confused on that. I myself don't "follow patterns blindly", I just find whatever I find interesting on all those patterns and use it for a good purpose.
If you are sure your buttons will never change (or ALL your buttons will change at the same time), then there's no need for all of these. Whether going full-throttle on this, or whether to apply the GTD (Getting Things Done) principle, is up to you.
Applying patterns, decoupling dependencies, etc., takes time and effort, and depending on the project, deadline, budget, and possibility of it changing in the future, they are worth implementing or not.
Related
I don't think I explained my question very well in the title, so I'll do my best to do it here.
I have an abstract class called Song, a class that extends it MidiSongand then I have a SongCreator interface and a MidiSongCreatorclass that implements it. I would like to have a way to store lots of SongCreators so I can call their Create method but the problem is, since the SongCreators will each be a MidiSongCreator I am wondering how I should initialize each MidiSongCreator since it takes a MIDIPlayer and other things to help initialize it which doesn't have a static reference to it. Should I create a static class that holds lots of SongCreators? Should I not make the SongList class static?
What is looks like:
public abstract class Song{
public IList<Playable> notes { get; private set; }
public SongPlayData Start(){
// calls onStartEvent
return CreateSongData();
}
protected abstract SongPlayData CreateSongData();
public bool Update(SongPlayData songData, float songTime,List<SongPlayer> players) { // note that the players list is a list of people who are playing this game (this is a rhythm game) (doesn't have anything to do with MIDIPlayer
}
public void End(){
//calls end event
}
}
public class MidiSong : Song { // this is the class that needs the MIDIPlayer parameter
public MIDIPlayer midiPlayer;
protected MidiSong(MIDIPlayer player){
this.midiPlayer = player;
}
protected override SongPlayData CreateSongData() {
return new MidiSongData(midiPlayer);
}
}
public interface SongCreator<out T> where T : Song {
T Create();
}
public class MidiSongCreator : SongCreator<MidiSong>, IListenerObject { // this is the class that I need to store lots of instances of. the midiPlayer will probably be the same every time
private MIDIPlayer player;
public MidiSongCreator(MIDIPlayer player) {
this.player = player;
Init();
}
private void Init() {
player.midiListener.listener = this;
//
}
private void Clear() { // resets all the data so we can create another Song if we need to (even without entering stuff in)
if(player.midiListener.listener == this) {
player.midiListener.listener = null;
}
}
public MidiSong Create() {
MidiSong r = new MidiSong(player);
// I'm still going to implement calls to other methods from midiPlayer
Clear();
return r;
}
public void OnLoad(MidiFile file) {
// does stuff to load midi file (deals with individual events)
}
}
public class MasterSong : MonoBehaviour { // this should initialize last btw (It's in the Script Execution Order)
public MIDIPlayer midiPlayer;
public Song song;
public SongPlayData playData;
// Use this for initialization
void Start() {
// this is where I'd like to reference a SongCreator and call it's create method and Start the song
//for instance:
song = SongList.SONG_NAME.Create();
playData = song.Start();
}
void Update() {
}
}
It's a RhythmGame made with unity, but I didn't add the unity tag because I feel that this is more of a C#/design thing.
Also note, that I have my classes much more organized that just one file with all these.
I'm looking for ways to improve on the design that I have.
This is a design problem, domain design!
I suggest don't write code yet. Create a class diagram, with pen and paper, don't need to use tools in the beginning.
Try to determine entities - classes, interfaces etc - and the relationship among them. Just use boxes and arrow, don't need to put details yet. With boxes and arrows, you will be able to have a picture of your domain much more clearly. Keep refining and changing it, still at this high level, without details, until you are satisfied.
Then, step by step, refine it by adding details/properties such attributes and methods. This may cause to change the diagram from the first step.
I intentionally did not refer to specifics of you questions like the classes and interfaces you mentioned. Since, there is not enough information to comment on that. Secondly, and more importantly, you should start at high level of design and once that is done, then do coding based on your design.
Edit 1:If anyone has a better Title for that, feel free to tell me or edit it yourself.
Edit 2: Thanks for your contribution guys, the answer given is almost what I need with some tweaks and I'm thankful for the small stuff here. Really learnt much today!
Little stuff here that I'm banging my head on for a while now.
I want to create a Slideshow and want the logic in the Image objects itself.
The programm should be able to set a desired transition or just a random one so
I wanted to create a Transition Superclass with the general stuff and spezialize
it in the subclasses. So I have Transitions.cs (with no Code currently inside it)
and no derived class. I want it to be in the way of adding a single .cs file
extending Transitions.cs and not change any other code to implement a new Transition.
The Code I currently have looks something like this but I guess my
description is more helpful than the code
public class SlideImages : MonoBehaviour {
Image image;
Image nextImage;
int tracker;
private void Transition(int ID)
{
/*Something to choose a transition based on the ID
*Transitions.cs is the superclass of all different transitions
*f.e. Ken-Burns Effect, or scattered Transition which all extend from it
*/
}
~SlideImages()
{
//TODO: Pop and Push
}
}
I had the idea of something along the lines of static stuff to workaround that
looks like this but it doesn't work I suppose
public class Transitions : MonoBehaviour {
public static int TransitionID;
protected static int SubclassCount;
protected static void SetID()
{
TransitionID = Transitions.SubclassCount;
Transitions.SubclassCount++;
}
}
I did look into the state design pattern but I don't want to implement it as I just need the state to be chosen once and shortlived. The Image Objects themself only have a lifetime of around a few seconds. I don't want to do the usual if-nesting or just put all the code inside the SlideImages.cs. Is there any good guidance to it or stuff that goes very indepth into inheritance and such stuff?
Appreciate all the input.
There are two straight-forward solutions to what you want to do. Your basic problem is that you want to be able to dynamically add functionality to your program but you don't want to have knowledge of what has been added in order to use it. The most hack-ish way of doing it is to use Actions instead of subclassing. When you want to add another transition you just update an actions list like this:
public static class Transitions
{
private static Action[] TransitionStrategies = new Action[]
{
() => { /* One way of performing a transition */ },
() => { /* Another way of performing a transition */ },
() => { /* Keep adding methods and calling them here for each transition type */ }
}
public static void PerformTransition(int? transitionIndex = null)
{
int effectiveIndex;
// if the transition index is null, use a random one
if (transitionIndex == null)
{
effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
}
else
{
effectiveIndex = transitionIndex.Value;
}
// perform the transition
TransitionStrategies[effectiveIndex]();
}
}
The above approach is simple but all of the logic (or at least references to the logic depending on where you implement the actual work for the transitions) is in one place. It also has the potential to get quite messy depending on how many transitions you are adding and how many developers are touching this codebase. It also requires all functionality to be added by someone with access to the full codebase and requires a recompilation each time new transitions are added.
A more complex but much more maintainable and flexible approach in the long term is to use modules (or plugins for our purposes). Each transition in that approach is provided by either a shared module or a specific module and is a subclass of a base AbstractTransition class or an implementation of an ITransition interface depending on how you want to go about doing that. Use post-build tasks to place all of your module dlls in a single directory accessible to your main program (anyone else given permission can put transition module dlls there too). When your program launches, it dynamically loads all dlls from that directory (no recompilation required when new transitions are added as long as the right dlls are in that directory) and pulls out all of the classes implementing that interface. Each of those interface implementations are instantiated and placed into a data structure after which you can use a similar strategy to the above's PerformTransition method to perform a random one or one based on an ID instead of an index. I can edit this question with an example of that structure if you would like.
Edit: You didn't ask for it yet, but here's an example with plugins/modules.
First, create a project to load and run the transitions. This example will use a project called ModuleDemo. Give it a main method like this:
static void Main(string[] args)
{
// create a list to hold the transitions we load
List<AbstractTransition> transitions = new List<AbstractTransition>();
// load each module we find in the modules directory
foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
// this should really read from the app config to get the module directory
{
Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);
transitions.AddRange(dllAssembly.GetTypes()
.Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
.Select(type => (AbstractTransition) Activator.CreateInstance(type)));
}
// show what's been loaded
foreach (AbstractTransition transition in transitions)
{
Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);
// execute just to show how it's done
transition.PerformTransition();
}
Console.Read(); // pause
}
You'll notice that the method references an AbstractTransition class. Let's create a separate TransitionModule project for that now. This is the project that the modules will reference:
namespace TransitionModule
{
public abstract class AbstractTransition
{
public readonly int TransitionId;
public abstract void PerformTransition();
protected AbstractTransition(int transitionId)
{
TransitionId = transitionId;
}
// you can add functionality here as you see fit
}
}
Now that we have an abstract transition class for the plugins to implement and a functioning plugin loader, we can go ahead and create a few transition plugins.
I created a Modules folder for this in my solution but it doesn't really matter.
First module in a FlipTransition project:
using System;
using TransitionModule;
namespace FlipTransition
{
public class FlipTransition : AbstractTransition
{
public FlipTransition() : base(2)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing flip transition");
}
}
}
Second module in a SlideTransition project:
using System;
using TransitionModule;
namespace SlideTransition
{
public class SlideTransition : AbstractTransition
{
public SlideTransition() : base(1)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing slide transition");
}
}
}
Note that each of those projects needs to reference the TransitionModule project but the main project doesn't need to know about any of the other projects.
Now we have 2 transition plugins and a plugin loader. Since the plugin loader is going to load the modules from a Modules directory, go to the /bin/Debug directory of the main project and make a Modules directory. Copy all of the dlls from the /bin/Debug directories of the transition plugin projects into that directory as well. All of this can be automated with post-build tasks later on.
Go ahead and run the program. You should get output like this:
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition
There's a lot you can do to make this more elegant, but this is at least a simple example of how you can use a plugin-based architecture to provide what you need.
You could try playing around with abstract classes, create a base abstract class for image transitioning;
public abstract class ImageTransition
{
protected int imageId { get; set; }
public Dictionary<int, Image> ImageDictionary { get; set; }
protected abstract void TransitionToNextImageId();
public Image GetNextImage()
{
TransitionToNextImageId();
return ImageDictionary[imageId];
}
}
You then create new Transition types that inherit from this base class and have their own implementation of the TransitionToNextImageId method;
public class InTurnImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
if(this.imageId < ImageDictionary.Count)
this.imageId ++;
}
}
public class RandomImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
imageId = new Random().Next(0, ImageDictionary.Count);
}
}
This allows you to build up some custom transitions however you wish.
-Edit-
You would of course fill the dictionary ImageDictionary before calling the GetNextImage method.
I'm trying to create a mechanism that will allow the application to decide (in runtime) whether to execute some functionality.
"Some Functionality" can be anything, it can be c# code which is contained in several classes in several dlls, it can be UI, it can be database query execution, etc.
Most importantly, it should fit in the current existing infrastructure I have, which I cannot re-design and build from scratch.
The more I think of it, it seems like the only solution I can use would be to hold some table which will be the "functionality repository" and it will tell (by unique key) if a functionality is on / off.
Then in code, I will have to place in each spot which handles such functionality an if else statement.
E.g.
If(functionalityEnabled)?
DoFunctionality()
Else
DoTheUsusal()
Is there a better way or a better design to implement it? I would like to keep the solution as simple as possible, but on the other hand, this solution is really ugly and will eventually make my code looks like spaghetti code.
Your thoughts will be appreciated,
I'm using c# with sql server, web api for web services.
Edit:
I want to say that I appreciate the time and effort of everyone answering my question, there were some really interesting ideas that you brought up.
I eventually marked #dasblinkenlight answer since it suited by need the best, though other answers here are really good and may be useful to others.
Thank you.
If you have two classes that implement the same interface, your application can call the functionality (methods, properties) of the class without knowing exactly if it is calling the basic functionality or the alternative functionality:
IFunctionalityX {
DoIt();
}
class BasicFunctionalityX: IFunctionalityX {
public DoIt() {
// Default behaviour goes here
}
}
class PluginFunctionalityX: IFunctionalityX {
public DoIt() {
// Alternative functionality.
}
}
If PluginFunctionalityX shares parts of its implementation with BasicFunctionalityX, you may inherit it from the other, but whether you do or not doesn't really matter. As long as you use the interface, that is what counts, and you can use this method regardless of whether the classes are related or not.
In the initialization of your program, you can make the decision once and create an instance of the right class. You may store this class in some container that holds all your functionalities. FunctionalityX is a property of interface IFunctionalityX, and you can make other interfaces (and properties) for other functionalities.
if (functionalityXEnabled) {
FunctionalityContainer.FunctionalityX = new PluginFunctionality();
} else {
FunctionalityContainer.FunctionalityX = new BasicFunctionality();
}
Then, in the rest of your application, you can call your functionality through:
FunctionalityContainer.FunctionalityX.DoIt();
Instead of implementing this from scratch you may use a dependancy injection library, like Unity. This also allows you to more easily get an instance of the right functionality at the time you need it without having to create them all at the start of your program, and without writing elaborate constructor code for all fucntionalities.
You want to dispatch your code differently at runtime dependent on a configuration setting. Conditionals and polymorphism are two ways of doing so.
Conditionals
At runtime, check for values using if, switch or other lookup methods. You're already doing these.
if (configFile.cloudAccount == null) {
saveFileToDisk();
} else saveFileToCloud();
Advantages
They're conditionals, you really can't avoid having to do one at some point in any nontrivial development project
Disadvantages
Doing them at every point in your application would be painful, though. So they're best combined with other strategies to minimise their use
Polymorphism
When loading your application, read through the configuration file and construct your application's components accordingly:
interface IFileSaver { /* Used to save files in your application */ }
class DiskSaver : IFileSaver { /* The default file saving class */ }
class CloudSaver : IFileSaver { /* If they've configured a cloud account */ }
// EXAMPLE USE
int Main (...) {
// Setup your application, load a config file.
// You'll need to check the config with a conditional
// here (uh oh) but other components of your application
// will just use the IFileSaver interface
if (configFile.cloudAccount != null) {
YourApplication.FileSaver = new CloudSaver(configFile.cloudAccount);
} else {
YourApplication.FileSaver = new DiskSaver();
}
}
// Somewhere else in your application
void SaveCurrentDocument() {
// No if's needed, it was front loaded when initialising
// the application
YourApplication.FileSaver.Save();
}
Advantages
Fits in nicely with object-oriented design
All your configuration checks are front loaded. After loading in the correct classes the rest of your program will use them, oblivious to their actual implementation. Because of that, you don't need to do if checks throughout your code.
Compiler will be able to statically check type errors in your approach
Disadvantages
Only as flexible as your class's interface. Maybe you want some extra steps and checks to occur with a CloudSaver, they'd better fit into the pre-existing interface; otherwise, they won't happen.
Long story short - conditionals let you explicitly perform the checks whenever they're needed so, in principle, you get a lot of procedural flexibility. For example, maybe the SaveAs routine needs to save files slightly differently than the Save routine. However, as you've identified, this leads to long repetitive code. In those cases, structuring your code to use polymorphism might help out.
Either way, you will almost certainly need to have some amount of conditional checks wherever there is flexibility in your application.
Note: There are many other ways of achieving runtime config checks, I'm just pointing out the most common (and usually straightforward)
A once-popular quip among OO programmers has been that every conditional in the code indicate a missed opportunity to subclass. Although this rule is far from being universal, and it falls short when it comes to composition, there is a grain of truth to it, especially when you see the same condition popping up in multiple ifs across different methods of the same class.
A common way of dealing with ifs like that is using some combination of inheritance and composition, and moving the decision to a single place where your object is being created.
The inheritance way looks like this:
interface Doer {
void doSomething();
}
class BasicDoer implements Doer {
public void doSomething() {
...
}
}
class EnhancedDoer extends BasicDoer {
public void doSomething() {
base.doSomething();
...
}
}
// At construction time:
Doer doer;
if (someCondition)
doer = new BasicDoer();
else
doer = new EnhancedDoer();
The composition way looks like this:
interface Doer {
void doSomething();
}
// Create several implementations of Activity, then...
// At construction time:
List<Doer> doers = new ArrayList<>();
if (someCondition1)
doers.add(new SomeKindOfDoer());
if (someCondition2)
doers.add(new AnotherKindOfDoer());
if (someCondition3)
doers.add(new YetAnotherKindOfDoer());
Now instead of an if you do this:
for (Doer d : doers) {
d.doSomething();
}
If it's just a single condition then you have no choice but to use if else and is perfect for single conditions.
If you have more then 1 condition, you may think of using Switch statement.
As far as you are worried about your code going to look complicated with if else statement, put your code within functions,
if(condition)
{
DoThis();
}
else
{
DoSomethingElse();
}
Maybe something similar to strategy design pattern (incapsulation of behaviour) will make it more managable if functionality doesn't require lots of interaction with object data (though interaction is possible). Pros: readable extendable code, cons: lots of code.
namespace SomethingLikeStrategy
{
public interface Behaviour {
void doThis();
void changeM(ref int m);
void doThat();
}
public class BehaviourOriginal : Behaviour {
public void doThis() {
Console.WriteLine("foo");
}
public void changeM(ref int m) {
m = 20;
}
public void doThat() {
throw new Exception("not implemented");
}
}
public class BehaviourSpecial : Behaviour {
public void doThis() {
Console.WriteLine("bar");
}
public void changeM(ref int m) {
m = 10;
}
public void doThat() {
throw new Exception("not implemented");
}
}
public class MyClass {
Behaviour mBehaviour;
int mM = 0;
public MyClass() {
mBehaviour = new BehaviourOriginal();
}
public void setSpecialBehaviour(bool special) {
if (special) {
mBehaviour = new BehaviourSpecial();
} else {
mBehaviour = new BehaviourOriginal();
}
}
public void doThis() {
mBehaviour.doThis();
}
public void doThat() {
mBehaviour.doThat();
}
public void changeM() {
mBehaviour.changeM(ref mM);
}
public void printM() {
Console.WriteLine(mM);
}
}
class Program
{
public static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.doThis();
myClass.setSpecialBehaviour(true);
myClass.doThis();
myClass.setSpecialBehaviour(false);
myClass.printM();
myClass.changeM();
myClass.printM();
myClass.setSpecialBehaviour(true);
myClass.changeM();
myClass.printM();
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
I have read a few tutorials on the topic of the Decorator Pattern similar to this one. The basic example is a cake as in this tutorial, or a pizza as in other tutorials, and the decorators usually pass through values and modify them on the way (as in, every PizzaDecorator adds a small amount onto the price, thus returning the price of the pizza + all decorators). Now, that's certainly a nice example, but I am having a little trouble applying this to a less edible problem.
Suppose I have a base class that takes an input, according to which it modifies its state. Some of these state modifications cause an event to be raised which passes a value that could be considered the output. Now suppose the following features I'd like to individually add as decorators:
A buffer for the output
A history of the input
Another type of input (e.g. interprets a set of characters as allowed byte input values)
Individually, they are not so much of a problem. The basic functionality of the class (i.e. the TakeInput(byte input) and event Handler OutputAvailable) reside in an interface that the base class as well as the decorators can inherit (do I really need the extra abstraction layer as in the given example, i.e. a separate interface for the Decorator classes which in turn inherits from the base interface?). Now, if I implement the input cache in a decorator, how do I add it in such a way, that the next decorator would not hide it again? If I added, say, a list to simply store the input and made it available via a property, that property would be hidden should I decide that I also want the output buffered. I could keep references to both decorators around- but that would be rather messy, or so I think, because I am going to need quite a bunch of decorators. If I derived from the Decorator, the inheritance mess that I initially wanted to avoid by applying this pattern would not go away. How do I solve this problem?
As requested, a piece of code that illustrates my problem. (Or so I hope, anyway)
public interface ISampleClass
{
event OutputHandler OutputAvailable;
void TakeInput(byte input);
}
public class BaseSampleClass : ISampleClass
{
public event OutputHandler OutputAvailable;
void TakeInput(byte input)
{ // To keep things simple:
this.OutputAvailable(input);
}
}
public class SampleClassInputCacheDecorator : ISampleClass
{
private ISampleClass decoratedClass;
private List<byte> inputCache;
public event OutputHandler OutputAvailable;
public SampleClassInputCacheDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public List<byte> InputHistory { get { return this.inputCache; } }
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
}
public class SampleClassCharInputAdapterDecorator : ISampleClass
{
private ISampleClass decoratedClass;
public SampleClassCharInputAdapterDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
public void TakeInput(char input)
{
switch (input)
{
case 'a':
this.TakeInput(27);
break;
case 'b':
// You get the idea...
}
}
}
// Now, I want to use the base class and get the benefit of both decorators:
ISampleClass smpl = new BaseSampleClass();
smpl = new SampleClassInputCacheDecorator(smpl);
smpl = new SampleClassCharInputAdapterDecorator(smpl);
// Dang, the input gets cached, but I can't access the InputHistory property.
Decorator is about altering the contracted behavior. You decorator adds completely new behavior, irrelevant in the context of the first one, and not being the part of the contract (the interface).
In fact SampleClassInputCacheDecorator is not a decorator - its actions are completely irrelevant from the ISampleClass point of view, as they don't influence TakeInput and OutputAvailable at all. It just depends on the ISampleClass chain, but does not "decorate" it. Proxy pattern seems more suitable here.
I am creating an application that the user will be able to setup a series of functions to run on an object (image manipulation stuff).
Each different function has either no configurable options, or its own uniques set of options.
This is hard to explain, so let me show a simple example:
Image opened (always happens)
Remove border (two options)
Despeckle image (5 options)
Crop image (10 options)
Save image
The problem is that I need to allow the user to create a custom series of cleanup functions that will be used to process images in bulk.
What is the best way to go about this?
I'd highly recommend you look into the Command Pattern:
http://www.codeproject.com/KB/architecture/Command_Pattern.aspx
Essentially, this involves creating "Command" subclasses for each type of action the user can perform - and pushing them unto a stack once the command has been executed.
Each command knows how to "do" itself, and also "undo" itself.
Thus, undo is a relatively straight forward process of popping commands off the stack, and calling the undo method on them.
Because each instance of a Command can contain it's own state ("options"), you can create exactly the commands you want to use ahead of time, and "batch" them to get the result you are looking for.
pseudo-code:
public class ImageEditor
{
public Stack<Command> undoList = new Stack<Command>();
public void executeCommand(Command command)
{
command.performAction(this);
undoList.push(command);
}
public void undo()
{
undoList.peek().undoAction(this);
undoList.pop();
}
}
public interface ICommand
{
void performAction(ImageEditor editor);
void undoAction(ImageEditor editor);
}
public class CreateBorderCommand : ICommand
{
public int BorderWidth { get; set; }
private Border MyBorderBox { get; set; }
public void performAction(ImageEditor editor)
{
MyBorderBox = new Border(BorderWidth, editor.frame);
editor.addElement(MyBorderBox);
}
public void undoAction(ImageEditor editor)
{
editor.removeElement(MyBorderBox);
}
}
Later on:
ImageEditor editor = new ImageEditor();
editor.executeCommand(new CreateBorderCommand() { BorderWidth = 10 });
...
If you really want, you could make it a little more involved, and make all of the command definitions serializable - allowing you to create a list of them and read in the list and execute them later.
This can be solved by one of the standard 'Gang Of Four' design patterns. You should spend a bit of time reading about the Command Pattern. This pattern allows you to encapsulate the operations performed on an object within classes that implement the same interface. In your example, each of your steps becomes a command. Once you have a common interface for your commands you can then compose them into Macros.