-1

I have 2 implementation of the interface:

public interface MyInterface{
    void getCollectedData(MyData mydata);
}

public class MyImpl implements MyInterface{
    public void getCollectedData(MyData mydata){
         ServiceResult result = new ServiceResult();
         .....
         result.setName(myData.getServiceName());

    }
}

public class MyImpl2 implements MyInterface{
    public void getCollectedData(MyData mydata){
         ServiceResult result = new ServiceResult();
         .....
         result.setName(myData.getTargetName());

    }
}

As you can see, the getCollectedData method in both implementations is almost the same. The only thing that differs in the implementation of the method, is that each implementation sets different name.

However, the method is very large (lot of setting parameters that are the same) and if is very mucb redundant to have the same method body in both implementation when only one line differs.

What is reasonable way to solve this? What first came to my mind is to create a base method to set all parameters and then set other params in the method itself:

public interface MyInterface{
    void getCollectedData(MyData mydata);
    default ServiceResult fillData(MyData mydata){
        ServiceResult result = new ServiceResult();
         // set data
        return result;

    }
}

public class MyImpl implements MyInterface{
    public void getCollectedData(MyData mydata){
         ServiceResult result = fillData(mydata);
         result.setName(myData.getServiceName());

    }
}

public class MyImpl2 implements MyInterface{
    public void getCollectedData(MyData mydata){
         ServiceResult result = fillData(mydata);
         result.setName(myData.getTargetName());

    }
}

However by this i have to return new object and then modify its state. In my particular case, the object's properties are set with setters and are not immutable, but what if the objects will have to became immutable in the near future, or the same problems appears with immutable object?

What is the most reasonable way to handle this and not being redundant?

Thanks for help!

2
  • How about a class with implementation which takes an argument to set name in the constructor and inherited by derived class? Commented Aug 23, 2021 at 9:41
  • Can you change the MyInterface.getCollectedData method to accept two parameters, MyData mydata and Supplier<String> nameSupplier? You could then pass in a lambda when calling it getCollectedData(data, () -> data.getServiceName()). Or perhaps use a Function<MyData, String> and do getCollectedData(data, (d) -> d.getServiceName()). Then you only need a single implementation. Sometimes code duplication is only apparent; only DRY out the code if you don't expect the two methods to evolve in significantly different directions over time (i.e. the code repetition isn't circumstantial). Commented Aug 23, 2021 at 12:41

2 Answers 2

1

Template method or Strategy pattern could solve the problem of reuse the source code. However, as you indicate, it's likely that the hidden problem lies in the software design.

From the example code, it seems like the decomposition was based on data rather than behavior, which sometimes prevents object-oriented principles. Resolving that requires more contextual information than is provided, so I can't do more than make this book recommendation.

0

It it's important to you that the result object is (or could be) immutable, then your base class should have a method collectData() that takes the raw data and the name to stick on it. Then all subclasses can do their work simply by calling the superclass method with an appropriate name parameter filled in.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.