Archive for category Design Patterns

Multiple Inheritance with Strategy Pattern

When I was introduced to programming languages like Java and C# (coming from C++), one of the things that I really missed was Multiple Inheritance. That is, in these languages we could not say something like:

class AllRounder : Batsman, Bowler { }

These languages offer interfaces to establish polymorphism. That is we can say (in C#):

class Batsman
{
     void Bat()
     {  Console.WriteLine("Do batting.");  }
}
interface IBowler
{
     void Bowl();
}
class Bowler : IBowler
{
     public void Bowl()
     {  Console.WriteLine("Do bowling.");  }
}
class AllRounder : Batsman, IBowler
{
     public void Bowl()
     {  Console.WriteLine("Do bowling.");  }
}

Do you see a problem here…? I do.

The problem is that the Bowl() is implemented twice, although the code it contains is by definition the same. Its a shame calling this code ‘Multiple inheritance’ because actually interfaces do not inherit anything. They just ensure a contract. The only feature of inheritance that interface provide is Polymorphism. You can say:

IBowler bowler = new AllRounder();
bowler.Bowl();

But the problem with duplication is that if we need changing Bowl() in the Bowler class we will almost always require changing the Bowl() implementation in the AllRounder class. The are a few ways to get around this. The key to all solutions I can think of at the moment is to introduce a layer of abstraction i.e. wrap the code of Bowl() into code commonly accessible to both. I’ll choose using the Strategy Pattern

interface IBowlingBehavior
{
    void PerformBowling();
}
interface IBowler
{
    IBowlingBehavior BowlingBehavior { get; set; }
    void Bowl();
}
class Batsman
{
    void Bat()
    {  Console.WriteLine("Do batting.");  }
}
class Bowler : IBowler
{
    public IBowlingBehavior BowlingBehavior { get; set; }
    public void Bowl()
    {  BowlingBehavior.PerformBowling();  }
}
class AllRounder : Batsman, IBowler
{
    public IBowlingBehavior BowlingBehavior { get; set; }
    public void Bowl()
    {  BowlingBehavior.PerformBowling(); }
}
class DefaultBowlingBehavior : IBowlingBehavior
{
    public void PerformBowling()
    {  Console.WriteLine("Do bowling.");  }
}

This allows us to implement the bowling code in one place as well as select one of the many implementations of BowlingBehaviors at runtime!

class SpinBowlingBehavior : IBowlingBehavior
{
    public void PerformBowling()
    {  Console.WriteLine("Do spin bowling.");  }
}
class FastBowlingBehavior : IBowlingBehavior
{
    public void PerformBowling()
    {  Console.WriteLine("Do fast bowling.");  }
}

and later we can say…

Bowler fastBowler = new Bowler { BowlingBehavior = new FastBowlingBehavior() };
fastBowler.Bowl(); //Bowl Fast
fastBowler.Bowl(); //Bowl Fast
fastBowler.BowlingBehavior = new SpinBowlingBehavior();
fastBowler.Bowl(); //Bowl Slow, fool the batsman
Advertisements

, , , ,

2 Comments