Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using marker classes to control logic flow

Tags:

c#

.net

I have been going through some code seen that a colleague of mine is using 'marker classes' to control program logic (see contrived example below). It seems to work well, and the code reads really nicely, but there is just something about it that smells...

namespace ConsoleApplication4983
{
    public class MyClass
    {
        static void Main()
        {
            var c = new MyClass();
            c.DoSomething(new Sequential());
            c.DoSomething(new Random());
        }

        public void DoSomething(ProcessingMethod method)
        {
            if (method is Sequential)
            {
                // do something sequential
            }
            else if (method is Random)
            {
                // do something random
            }
        }
    }

    public class ProcessingMethod {}
    public class Sequential : ProcessingMethod {}
    public class Random : ProcessingMethod {}
}

What would be a better way of achieving the same effect? Enums? Attributes?

like image 582
KevinT Avatar asked May 07 '09 14:05

KevinT


2 Answers

Marker interfaces are a better practice as they offer much more flexibility.

However in this specific case I think that virtual dispatch is a better solution.

using System;

namespace ConsoleApplication4983
{
    public class MyClass
    {
        static void Main()
        {
            var c = new MyClass();
            c.DoSomething(new Sequential());
            c.DoSomething(new Random());
        }

        public void DoSomething(ProcessingMethod method)
        {
            method.Foo();
        }
    }

    public class ProcessingMethod
    {
        public virtual void Foo() { }
    }
    public class Sequential : ProcessingMethod
    {
        public override void Foo() { }
    }
    public class Random : ProcessingMethod
    {
        public override void Foo() { }
    }
}
like image 109
Andrew Hare Avatar answered Nov 07 '22 06:11

Andrew Hare


What you'd like to do is replace this with a strategy pattern. A strategy defines how something is done -- i.e., an algorithm.

public interface IProcessingMethod
{
    void Process();
}

public class SequentialProcess : IProcessingMethod
{
    public void Process( IProcessable obj )
    {
         do something sequentially with the obj
    }
}

public class ParallelProcess : IProcessingMethod
{
    public void Process( IProcessable obj )
    {
        do something in parallel with the obj
    }
}

public interface IProcessable
{
    void Process( IProcessingMethod method );
}

public class MyClass : IProcessable
{
     public void Process( IProcessingMethod method )
     {
         method.Process( this );
     }
}

...

var obj = new MyClass();
obj.Process( new SequentialProcess() );

Now if I have a new type of ProcessingMethod, I simply need to create the class for that method and change the code that determines what processing method is injected to the Process method of my IProcessable object.

like image 40
tvanfosson Avatar answered Nov 07 '22 07:11

tvanfosson