模板方法和继承或组成

时间:2019-02-22 09:42:34

标签: java inheritance design-patterns composition template-method-pattern

我有这些课程:

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

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

还有一些使用模板方法模式实现的操作。具有算法的基类:

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);
}

两个带有实现模板方法的孩子:

@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());
    }
}

我的问题:

  1. 如何重写此代码以使用合成?

  2. 我是否正确理解使用模板方法时会附加继承?

模板方法是避免重复的好方法。但是,如果它将我绑定到继承,还有什么其他方法可以避免代码重复?在我的示例中,如何使用合成? (用其他方法代替模板方法吗?)

2 个答案:

答案 0 :(得分:0)

您可以使用代理代替模板模式:

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);
    }
}

请注意,这将允许您创建类Operation和接口。

更新

另一种可能性是定义操作顺序和打印操作(甚至更多代码):

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);
    }
}

您现在可以使用以下代码:

    Operation<MyClass> print = new PrintOperation<>();
    Operation<MyClass> seq = new OperationSequence<>(
            print, (t) -> {doSomethingWith(t);}, print);

答案 1 :(得分:0)

  

1)如何重写此代码以使用合成?

Strategy Pattern是一种方法。本质上,您可以通过将操作传递到数据中而不是将数据传递到操作中来反转数据和操作之间的关系。这是一个根本性的变化,因为使用了具有状态和行为的“真实”对象而不是数据类。

  

2)我是否正确理解使用模板方法时会附加继承?

是的,模板方法模式基本上是基于继承的。