views:

374

answers:

4

I am basically trying to implement a Strategy pattern, but I want to pass different parameters to the "interfaces" implementation (that inherit from the same object) and don't know if this is possible. Maybe I'm choosing the wrong pattern, I get an error similar to

'StrategyA' does not implement inherited abstract member 'void DoSomething(BaseObject)'

with the code below:

abstract class Strategy
{
 public abstract void DoSomething(BaseObject object);
}

class StrategyA : Strategy
{
 public override void DoSomething(ObjectA objectA)
 {
  // . . .
 }
}

class StrategyB : Strategy
{
 public override void DoSomething(ObjectB objectB)
 {
  // . . .
 }
}

abstract class BaseObject
{
}

class ObjectA : BaseObject
{
 // add to BaseObject
}

class ObjectB : BaseObject
{
 // add to BaseObject
}

class Context
{
   private Strategy _strategy;

 // Constructor
 public Context(Strategy strategy)
 {
  this._strategy = strategy;
 }

    // i may lose addtions to BaseObject doing this "downcasting" anyways?
 public void ContextInterface(BaseObject obj) 
 {
  _strategy.DoSomething(obj);
 }

}
+4  A: 

It sounds like you're actually trying to reinvent the Visitor pattern, instead of just using the Strategy pattern the way it was intended.

Also, since you're using C#, I'd recommend reading Judith Bishop's paper titled On the Efficiency of Design Patterns Implemented in C# 3.0. This covers multiple approaches to the visitor pattern in detail, and has some interesting, related useful ideas.

Reed Copsey
i am converting 2 different file formats to a different format, if that helps - i'm converting formats A and B both to C
One interface, with a ObjectC ConvertToC() method, is probably all you need, in that case. Format A and Format B (or a class that works with those formats) just needs to implement that interface, and you're done.
Reed Copsey
but if wanted 2 methods - ObjectC ConvertToC(ObjectA a), ObjectC ConvertToC(ObjectB b), I think I would still have the same problem
You could make your interface: ConvertToC(). Then just construct your converters with the approrpiate objects themselves (ie: AConverter convert = new AConverter(a); ObjectC result = convert.ConvertToC();
Reed Copsey
If you really want to support multiple ConvertToC(multipleClassesHere obj) , then you probably want the visitor pattern, or a variant as proposed in that paper.
Reed Copsey
+1  A: 

The strategy pattern is meant to provide different behaviour on input objects of the same type.

What you're actually trying to do is context-dependent, and I'm not sure it can be seen from the code that was posted.

Jon Seigel
+2  A: 

In C# method signature includes its name, type parameter list and formal parameter list. In the code above "overrides" have different signatures than virtual method and thus it is not allowed.

The core idea behind Strategy Pattern is to define set of interchangeable algorithms with details hidden inside. But if your strategies differ (by type) in what they can accept as input they are no longer interchangeable. So it seems this a wrong pattern to use in this situation.

Dzmitry Huba
A: 

You could create a Parameters class like so:

public class Parameters
{
  public ObjectA {get; set;}
  public ObjectB {get; set;}
}

The alter your methods to accept Parameters such as:

class StrategyA : Strategy
{
 public override void DoSomething(Parameters parameters)
 {
      //  Now use ObjectA
      if(parameters.ObjectA.SomeProperty == true)
      { ... }
 }
}

This way you can additional parameters should your requirements change in the future. Another alternative is to use Dictionary<string, object> where you can do:

class StrategyA : Strategy
{
     public override void DoSomething(Dictionary<string, object>parameters)
     {
          //  Now use ObjectA
          var someProperty = (bool)parameters["SomeProperty"];
          if() ...
     }
}
David Robbins