Consider having a class named ClassA with multiple methods like MethodA(int a), MethodB(int b), … . I have multiple instances of ClassA and I want to write a manager which decides which instance should be called when calling any method based on argument or any context. For example consider following approach:
class ClassA {
public void MethodA(int a) {
// some code
}
public void MethodB(int a) {
// some code
}
}
Class Manager {
ClassA evenClassA = new ClassA();
ClassA oddClassA = new ClassA();
public void MethodA(int a) {
Choose(a).MethodA(a);
}
public void MethodB(int a) {
Choose(a).MethodB(a);
}
private ClassA Choose(int a) {
if (a % 2 == 0)
return evenClass;
else
return oddClass;
}
}
// Somewhere else
Manager manager = new Manager();
manager.MethodA(2);
manager.MethodB(1);
This approach works but it smells. I need to write all methods of ClassA in the Manager which does the same thing and add any method in the future to both classes. Another approach is that the Manager class only have the Choose method:
Class Manager {
ClassA evenClassA = new ClassA();
ClassA oddClassA = new ClassA();
private ClassA Choose(int a) {
if (a % 2 == 0)
return evenClass;
else
return oddClass;
}
}
// Somewhere else
Manager manager = new Manager();
manager.Choose(2).MethodA(2);
manager.Choose(1).MethodB(1);
But it’s buggy and the Choose argument must be the same as the method argument which can be used wrong.
Is there any other cleaner approach?
CodePudding user response:
I need to write all methods of ClassA in the Manager which does the same thing and add any method in the future to both classes
This would be suitable when using the decorator pattern, I.e. your manager implements the same interface as the actual implementations. This is useful in some cases since users do not need to know if they are using a manager, or something else.
That the Manager needs to implement all methods in the interface is usually not a large problem, since the code for each method tend to be very simple. But you always need to be careful when designing interfaces to ensure they represent a useful abstraction, and reduce the chance of future breaking changes.
Another approach is that the Manager class only have the Choose method:
This would probably be similar to the factory pattern, where one class is responsible creating objects to be used by something else. This has a possible advantage in that the choice can be made from something other that the method parameters.
Each pattern are useful in some cases, but it is hard to tell from a toy example like this what pattern would be most suitable. If your choice is guaranteed to be based on the method parameters I would probably go for the decorator pattern. There is also a possibility something completely else would be most suitable.
CodePudding user response:
why not make Manager
a factory, that returns an instance of ClassA
? Then just call the method on that returned instance instead of on the manager.
class Manager
{
MyBaseClass Choose(int a) => a % 2 == 0 ? new ClassA(a) : new ClassB(a);
}
That of course assumes both classes derive from some common base-class or interface and have a constructor-arg for the number being processed. Then you can just omit the param from your actual methods and just use this:
var manager = new Manager();
MyBaseClass instance = manager.Choose(1);
instance.MethodA(); // no need to provide the args here again
instance.MethodB();