views:

160

answers:

2

Sorry if this sounds simple, but I'm looking for some help to improve my code :)

So I currently have the following implementation (which I also wrote):

public interface IOptimizer
{
    void Optimize();
    string OptimizerName { get; }
}

public abstract AbstractOptimizer : IOptimizer
{
    public void Optimize()
    {
        // General implementation here with few calls to abstract methods
    }
}

public abstract AbstractPriorityOptimizer : AbstractOptimizer 
{
     // Optimize according to priority criteria.    

     string Name 
     { 
        get { return "Priority Optimizer"; }
     }      
}

Then I have technology-specific concrete classes:

TechnologyXPriorityOptimizer : AbstractPriorityOptimizer 
TechnologyYPriorityOptimizer : AbstractPriorityOptimizer 


Now I'm trying to add a generic optimizer, one that optimizes for conditions other than priority, so my attempt:

public abstract AbstractGenericOptimizer : AbstractOptimizer 
{
     // Optimize according to a generic criteria.    

     private readonly int param;

     public AbstractGenericOptimizer (int param) : base()
     {
          // param affects the optimization
          this.param = param;
     }        
}

and I also need technology-specific implementation just like the priority optimizer:

TechnologyXGenericOptimizer : AbstractGenericOptimizer 
TechnologyYGenericOptimizer : AbstractGenericOptimizer 


Q1. TechnologyXPriorityOptimizer and TechnologyXGenericOptimizer have the same exact "extra" methods because they involve the same technology. Is there a way to keep this method common to both inheritance branches ?

Q2. For AbstractGenericOptimizer, the optimizer has a special name for special values of the int param, so would it be a good idea to extend the base generic optimizer class (where param is hardcoded) and then for every division, have a technology-specific implementation:

AbstractSpecialName1Optimizer: AbstractGenericOptimizer
TechnologyXSpecialName1Optimizer: AbstractSpecialName1Optimizer
TechnologyYSpecialName1Optimizer: AbstractSpecialName1Optimizer

AbstractSpecialName2Optimizer: AbstractGenericOptimizer
....

What would be the best way to refactor this scenario ? I feel that there is a smarter way of reducing the number of inheritance levels.

Thanks!

+8  A: 

You should probably use containment instead of inheritance.

For example, you could make an abstract OptimizerStrategy class with concrete implementations for each technology, then make the GenericOptimizer and PriorityOptimizer take an OptimizerStrategy as a generic type argument or constructor parameter.

SLaks
Thank you for your suggestion. In this case, do I implement Optimize() in OptimizerStrategy class ? What should I do with IOptimizer ?
alhazen
I have no idea; it depends what the code actually does. However, probably both.
SLaks
+3  A: 

Ad hoc I tend to say that you cannot get your desired design by using inheritance only. You have to orthogonal inheritance paths - priority and generic on one side and technology X and Y on the other. You want to combine code from both paths in the possible four combinations but this would require multiple inheritance - inheriting from priority or generic and technology X or Y. Because C# does not support multiple inheritance, this will not work.

I would try to solve this by using interfaces and the strategy pattern. This should allow you to extract the code specific to all four core components into separate classes and then merge always two of them in each of the four desired combinations.

Daniel Brückner
Thanks for the link
alhazen