Saturday, May 24, 2014

Mediator in C++

New class, new project, same old people and they just can't get enough of my crazy singleton mediator goodness.  Now in exciting new C++ flavors!!

class Mediator
{
private:
 Mediator() {/*Filler!!*/}
 
 Mediator(const Mediator&) {/*Filler!!*/ }
 
 Mediator& operator = (const Mediator&) {/*Filler!!*/ }
 
 ~Mediator() {/*Filler!!*/ }
 
 static Mediator& Instance()
 {
  static Mediator instance;
  return instance;
 }
 
 std::map<std::string, std::vector<void (*)(void*)>> MediatorMap;
public:
 
 static void Register(std::string Key, void (*Function)(void*))
 {
  Instance().MediatorMap[Key].push_back(Function);
 }
 
 static void Unregister(std::string Key, void(*Function)(void*))
 {
  if (Instance().MediatorMap.count(Key) != 0)
  {
   Instance().MediatorMap[Key].erase(std::find(Instance().MediatorMap[Key].begin(),
         Instance().MediatorMap[Key].end(),
         Function));
  }
  if (Instance().MediatorMap[Key].size() == 0)
  {
   Instance().MediatorMap.erase(Instance().MediatorMap.find(Key));
  }
 }
 
 static void Call (std::string Key, void* Object = nullptr)
 {
  if (Instance().MediatorMap.count(Key) != 0)
  {
   for (std::vector<void(*)(void*)>::iterator It = Instance().MediatorMap[Key].begin();
        It != Instance().MediatorMap[Key].end();
               ++It)
   {
    (*It)(Object);
   }
  }
 }
 
 static void Clear()
 {
 Instance().MediatorMap.clear();
 }  
};

I started writing it as a template but the mixture of template and singleton were to much for my currently sick and heavily medicated self to figure out.  So, for now, instead of being able to use whatever kind of key you want you're currently stuck with using a string.

You might also be wondering why there are 230920934 Instance() calls.  Mostly so you can do the following:

Mediator::Register("Test", &TestFunction);
Mediator::Call("Test", "SPOOOON!!");
Mediator::Unregister("Test", &TestFunction);

For those of you new to singletons, normally you would have to do:

Mediator::Instance.Register("Test", &TestFunction);

But I don't like having to include the Instance method in the complete call.  Having all my methods static and referencing class variables through Instance() allows me to forgo that.  It's ugly, and there are probably better way to go about it but it is what it is.


[Edit/Update]

Changed the code just a little bit.  Changed the second parameter of our Call method to:

static void Call (std::string Key, void* Object = nullptr)

 This allows us to not have to send anything if our registered functions do not require an input.

Also added the Clear method.  This will completely empty our MediatorMap in the event this is ever required.  When will that be?  I don't know, but it's there if we need it.

As usual I am open to suggestions, comments, etc.  Thanks!

Wednesday, May 21, 2014

Expandable Enum Experiments

I approached this in response to a problem we had in a project last semester.  Yes I'm in college and 'we' means the people in my group.  The problem had to do with using strings as the keys for our Mediator class which is, in part, why I went with a template as apposed to hard coding it.  We came across a few cases where we had registered ...mediators (is that what they're called here?) with one string and tried to Call them with another.  The difference ended up being a capitalization issue but it took us a while to figure out why it wasn't working.

After the project was completed we discussed ways we could have done it better and we agreed that using enumerables would have been a better choice.  Outside of making sure you're using the right one there is no real possibility of spelling or capitalization mistakes.   MY main problem with this approach was the need to completely define our Enum in a centralized location.  If we ever added additional functionality to our project we would have to go and expand that Enum as needed.  I want the ability to expand out Enum as needed while maintaining the main purpose of an Enum.  So I came up with the following:

public class EnumBase
{
    // I don't know why we would want to count the number of objects
    // genereated from our EnumBase but it's here if we ever want it.
    private static int _Count = 0;
 
    // Class constructor.  Basic stuff.  Post increments Count,
    // and thus _Count, every time it's called.
    public EnumBase()
    {
        Count++;
    }
 
    // Our public interface to _Count.  Provides a public 'get'
    // and a private 'set' for access to our _Count.
    public static int Count
    {
        get
        {
            return _Count;
        }
        private set
        {
            _Count = value;
        }
    }
}


Pretty straight forward, and most of the guts of this class are unneeded, but it allows you to do the following:

public class EnumFoo
{
    public static readonly EnumBase One = new EnumBase();
    public static readonly EnumBase Two = new EnumBase();
}
 
public class EnumBar
{
    public static readonly EnumBase Red = new EnumBase();
    public static readonly EnumBase Blue = new EnumBase();
}


Which in turn allows you to the following:

Dictionary<EnumBaseList<Action<Object>>> Diction 
    = new Dictionary<EnumBaseList<Action<object>>>();
 
Diction.Add(EnumFoo.One, Func);
Diction.Add(EnumFoo.Two, Func2);
Diction.Add(EnumBar.Red, Func3);

I'm using the Dictionary from my Mediator class as an example, assuming we passed EnumBase to the template.  Using this method allows us to expand our list of unique "enumerables" as needed without having to continually expand a centralized Enum.

As always comments and suggestions are welcome!

Monday, May 19, 2014

Mediator Pattern/Class

 This is my Mediator class.  Right now I'm using it like a singleton but it can be changed back to a normal class easily.  The template "T" allows you to use whatever kind of key you like.  You can use any number of keys and have any number of Actions (functions/methods) registered under them.  Using the Call method allows you to execute all functions/methods under the given Key and pass to them (the functions/methods) any object you desire.

public class Mediator<T>
 {
     private static Mediator<T> _Instance = new Mediator<T>();
 
     private Dictionary<T, List<Action<object>>> 
         _Callbacks = new Dictionary<T, List<Action<object>>>();
 
     private Mediator() { }
 
     public static Mediator<T> Instance
     {
         get
         {
             return _Instance;
         }
     }
 
     public static void Register(T Key, Action<object> Action)
     {
         if (!Instance._Callbacks.ContainsKey(Key))
         {
             Instance._Callbacks[Key] = new List<Action<object>>();
         }
 
         Instance._Callbacks[Key].Add(Action);
     }
 
     public static void Unregister(T Key, Action<object> Action)
     {
         Instance._Callbacks[Key].Remove(Action);
 
         if (Instance._Callbacks[Key].Count == 0)
         {
             Instance._Callbacks.Remove(Key);
         }
     }
 
     public static void Call(T Key, object Message = null)
     {
         if (Instance._Callbacks.ContainsKey(Key))
         {
             Instance._Callbacks[Key].ForEach(Action => Action(Message));
         }
     }
 }


A couple side notes:

First, not having code specific formatting is making my ass twitch.  I need to find a way to remedy that to make the code easier to read.  At least it's keeping the tabbing, right?

Second, since this is my first code post I would like to make it clear that I am open to any and all suggestions in regards to improving my code.  Constructive criticism, while sometimes hard to swallow, is almost always welcome.

[Edit]

So the solutions to the code specific formatting appears to be installing Productivity Power Tools for MSVS 20## (whatever version you're using.)  This is done and now you can see my code in all its colorful glory!

New Beginnings!

So here it is.  I started this blog a few years back, posted a few times about things I don't care to explore again and now I'm coming back.  This time I will be posting about my coding adventures which is going to be painful I think.  I, like a lot of coders (I'm assured), am never satisfied with my code.  I always feel like there is a better way I could be doing things.  By feel I mean know.  Especially since I started college, working on my BACS and have learned just how much I don't know which is substantial.  But we all start somewhere, right?