2

I have these classes:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private int age;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Admin {
    private String name;
    private int age;
}

And I have some operations with template method pattern implementation. Base class with algorithm:

public abstract class Operation<T> {
    public void process(T t) {
        System.out.println(t);
        updateName(t);
        System.out.println(t);
    }

    protected abstract void updateName(T t);
}

Two children with implementation template method:

@Component
public class UserOperation extends Operation<User> {

    @Override
    protected void updateName(User user) {
        String newName = user.getName().toUpperCase();
        user.setName(newName);
    }
}

@Component
public class AdminOperation extends Operation<Admin> {

    @Override
    protected void updateName(Admin admin) {
        String name = admin.getName();
        StringBuilder builder = new StringBuilder();
        builder.append(name);
        StringBuilder reverse = builder.reverse();
        admin.setName(reverse.toString());
    }
}

My questions:

  1. How do I rewrite this code to use composition?

  2. Do I understand correctly that when using the template method, I attach to inheritance?

The template method is a great way to avoid duplication. But if it binds me to inheritance, what other ways are there to avoid code duplication? In my example, how can I use composition? (replace the template method with something else?)

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ip696
  • 6,574
  • 12
  • 65
  • 128

2 Answers2

1

1) How do I rewrite this code to use the composition?

The Strategy Pattern is one way. Essentially, you would reverse the relationship between data and operations by passing the operations into the data rather than passing the data into the operations. This is a fundamental change, because "real" objects (with state and behavior) are used instead of data classes.

2) Do I understand correctly that when using the template method, I attach to inheritance?

Yes, the Template Method Pattern is fundamentally based on inheritance.

jaco0646
  • 15,303
  • 7
  • 59
  • 83
0

Instead of template pattern you could have a proxy:

public abstract class Operation<T> {
    public abstract void updateName(T t);
}

public class OperationProxy<T> extends Operation<T> {
    private final Operation<T> delegate;

    public OperationProxy(Operation<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public void updateName(T t){
        System.out.println(t);
        delegate.updateName(t);
        System.out.println(t);
    }
}

Note that this would allow you to make class Operation and interface.

UPDATE

Another possibility is defining sequences of operations, and a print operation (even more code):

public interface Operation<T> {
    void updateName(T t);
}

public class OperationSequence<T> implements Operation<T> {
    private final Operation<T>[] steps;

    public OperationSequence(Operation<T>... steps) {
        this.steps = steps;
    }

    @Override
    public void updateName(T t){
        for (Operation<T> step: steps) {
            step.updateName(t);
        }
    }
}

public class PrintOperation<T> implements Operation<T> {
    @Override
    public void updateName(T t){
        System.out.println(t);
    }
}

You can now use the following code:

    Operation<MyClass> print = new PrintOperation<>();
    Operation<MyClass> seq = new OperationSequence<>(
            print, (t) -> {doSomethingWith(t);}, print);
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24
  • thanks for the example! but here the duplication problem is not solved. Because instead `System.out.println(t);` before and after `updateName` I have many lines of code and in each proxy class this code will duplicate. I need all classes to use the same algorithms. and change only the small parts of this algorithm – ip696 Feb 22 '19 at 09:57
  • @ip696 You don't have to refined the proxy class. You can implement Operation for the small part as delegate and create a proxy object with it. – Andrianekena Moise Feb 22 '19 at 10:28
  • it's all wrong. I have an algorithm. When performing this algorithm, different methods are called. with different signatures. and they are realized as heirs. What is the use of an array of classes with the same interface? most likely there is no alternative for the implementation of logic as in the template method – ip696 Feb 22 '19 at 10:43
  • A proxy works well when I have the same code, but I need to run another code before or after it. And I need the external code to remain (my algorithm) and only parts of the code inside change – ip696 Feb 22 '19 at 10:45