OOP-Design: interface methods with implementation-specific parameters

The topic already says:

Now I am thinking about the following design problem: I am defining an interface for a specific type of object that contains various methods. Now I have a problem that different implementations of this interface require additional / different method parameters (because the method of their implementation makes this necessary), which I cannot include in the interface, because they are not common to all implementations of the interface.

Now I understand that interface implementations can come with their own properties files, loading additional parameters from them, but what if these parameters should be passed at runtime?

For now, I can only think of going to Map<String, Object> parameters to overcome this problem - because JDK classes like DocumentBuilderFactory do something very similar by providing methods like setAttribute(String attName, Object attValue) this seems to be an acceptable approach to solving this problem. Nevertheless, I would be interested in how others solve such problems, alternative ideas?

I do not want to extract from the interface and add additional methods, since in my case I would have to throw a NotImplementException from the methods of the base interface.

UPDATE

What could be the potential problems of the Map approach? Implementing classes can freely ignore it if they cannot use additional parameters. Others can check whether the Map contains the required parameter names, check the type of their values ​​and use them if they are valid, throw an exception if not. I also saw that this is used for the abstract JAXBContext class, so this seems to be a general approach.

UPDATE

I decided to go to the map approach, since I do not see any obvious flaws, and it is also used in the JDK (yes, I know, this does not necessarily mean much :) Since I can not accept the answer to this question, I just come . Thanks for your input!

Yours faithfully,

- Qu

+4
source share
6 answers

Could you create subinterfaces that extend your (super) interface? anyway, I see a design problem if you need a method with different parameters depending on the implementation!

edit: code to clarify

 interface CommonBehaviour { void methodA(int aParam); } interface SpecificBehaviour extends CommonBehaviour { void methodB(int aParam, int anotherParam); } class SpecificBehaviourImpl implements SpecificBehaviour { void methodA(int aParam) { //do something common } void methodB(int aParam, int anotherParam) { //do something specific } } CommonBehaviour myObj = new SpecificBehaviourImpl(); 

EDIT: you can use the Command template: "Using command objects makes it easy to collect common components that need to delegate, organize, or make method calls when they are selected without having to know the owner of the method or method parameters." (source: wikipedia)

I don’t think that the Map approach would be good, I can take it as a correction of the existing code, which will allow you to have the parameter number and type, but without formal checks! You are trying to determine the general behavior (interface methods) based on a variable, runtime, state.

+1
source

An interface point must have what is common to all implementations. By trying to do this, you are destroying the whole reason interfaces exist.

If you absolutely must do this, there is a fairly simple way that I used to use.

My answer is in C ++, because I'm just not sure about the other languages. I am sure that there are ways to implement this in java as well.

SomeMethod(void* parameterData);

void* parameterData is a pointer to a structure containing your data. In each implementation, you know what you get. You may even have an enumeration to tell you what data you receive.

SSomeData* data = (SSomeData)parameterData

EDIT:

Another approach would be to create a new interface for the parameters: IParameterData .
Inside this interface, you have 2 methods: GetParameter(name) and SetParameter(name) .
For each implementation of your main interface, you create an implementation of IParameterData .

I hope this helps

+1
source

You should simply initialize each heir with your specific required parameters and allow the interface method to remain without parameters, as in:

Runnable Interface:

 public interface Runnable { public abstract void run(); } 

Implementation:

 public class MyRunnable { private final String myConcreteString; public MyRunnable(String myConcreteString) { this.myConcreteString = myConcreteString; } public void run() { // do something with myConcreteString } } 
+1
source

Can you invert the problem and implement an interface for the user of these objects, which they can request for additional parameters?

So, when you create instances of these objects that implement the common interface, you also pass (for example, to your constructor) an object that provides a way to access additional parameters that may be required.

Say your interface has a doSomething method with the parameter β€œa”, but you have an implementation that needs to know that β€œb” is inside this doSomething method. He will call 'getB' for the object provided by the constructor for this information.

0
source

You should enter a parameter object that represents a super-set of possible arguments.

0
source

If I were you, I would think about finding a suitable design template for your problem, and then try to bend the interface methods to suit your needs. Check out the strategy template for a start.

0
source

Source: https://habr.com/ru/post/1394389/


All Articles