繁体   English   中英

两个类共享相同和相似但不同的方法的 Java 设计模式

[英]Java design pattern for two classes sharing identical and similar but different methods

假设我的应用程序有一些实现为ClassAClassB 两者有一些相似之处,但也有不同之处。

  1. 这两个类都有一个start()方法,方法签名相同,但实现不同。
  2. 这两个类都有一个具有不同签名和不同实现的process()方法。
  3. 两个类都有相同的log()方法,即代码完全相同。

A级

public class ClassA {

    public String start(String s1, String s2) {
        startImplementation();
        return someString;
    }

    public String process(String s) {
        processingImplementation();
        return processedString;
    }

    private String log(String s) {
        logImplementation();
        return sharedString;
    }
}

B级

public class ClassB {

    public String start(String s1, String s2) {
        otherStartImplementation();
        return someString;
    }

    public String process(Long l) {
        otherProcessingImplementation();
        return processedString;
    }


    private String log(String s) {
        logImplementation();
        return sharedString;
    }
}

我在思考“设计模式”如何以更通用的方式组织它时遇到了麻烦。 从 3 开始,我可以轻松地将此方法移动到ClassAClassB扩展的超类。 但是我将/如何设计应用程序以便 1. 和 2. 也被考虑在内?

项目 1. 对我来说听起来有点像一个接口,但我不知道如何将它与项目 3 的超类结合起来。那么项目 2 呢?

我会这样设计,以便class Aclass B扩展一个通用抽象类,并为process方法的参数类型提供一个类型参数。

public abstract class BaseClass<T> {
    public abstract String start(String s1, String s2);

    public abstract String process(T value);

    protected final String log(String s) {
        // shared log implementation
    }
}
public class A extends BaseClass<String> {
    @Override
    public String start(String s1, String s2) {
        // A.start implementation
    }

    @Override
    public String process(String s) {
        // A.process implementation
    }
}
public class B extends BaseClass<Long> {
    @Override
    public String start(String s1, String s2) {
        // B.start implementation
    }

    @Override
    public String process(Long l) {
        // B.process implementation
    }
}

在 Java 9+ 中,您可以改为使用通用public interface Base<T>而不是抽象类,通过为log提供默认实现。 但是,这不允许您使log只有实现类可以访问,并且它不会阻止子类覆盖log

如何使用组合而不是继承? startprocess的实现可以由如下示例中的函数提供:

import java.util.function.BiFunction;
import java.util.function.Function;

class X<T> {
    public String start(BiFunction<String, String, String> f, String s1, String s2) {
        return f.apply(s1, s2);
    }

    public String process(Function<T, String> f, T t) {
        return f.apply(t);
    }

    // example
    public static void main(String[] args) {
        X<String> xString = new X();
        xString.start((s1, s2) -> s1 + s2, "a", "b");

        X<Long> xLong = new X();
        xLong.process((t) -> { Long tt = t * 2;return tt.toString(); }, 4L);
    }
}

与前面的示例相同,但在构造函数中提供了实现,并使用函数式接口而不是 lambdas。

import java.util.function.BiFunction;
import java.util.function.Function;

class StartFunctionExample implements BiFunction<String, String, String> {
    @Override
    public String apply(String s1, String s2) {
        return s1 + s2;
    }
}

class ProcessFunctionExample implements Function<Long, String> {
    @Override
    public String apply(Long t) {
        Long tt = (t * 2);
        return tt.toString();
    }
}

class Z<T> {
    private final BiFunction<String, String, String> startFunction;
    private final Function<T, String> processFunction;

    public Z(
            BiFunction<String, String, String> startFunction,
            Function<T, String> processFunction
    ) {
        this.startFunction = startFunction;
        this.processFunction = processFunction;
    }

    public String start(String s1, String s2) {
        return startFunction.apply(s1, s2);
    }

    public String process(T t) {
        return processFunction.apply(t);
    }

    // example
    public static void main(String[] args) {
        Z<Long> xLong = new Z(new StartFunctionExample(), new ProcessFunctionExample());
        xLong.start("a", "b"); // ab
        xLong.process(7L);     // 14
    }
}

让不同的类实现日志记录,处理可以通过实现服务接口的类来完成:

interface Processable {
  String start(String s1, String s2);
  process(String s);
}

class LogDecorator {

  private Processable p;

  public LogDecorator(Processable p) {
    this.p = p;
  }

  public String start(String s1, String s2) {
    p.start(s1, s2);
  }

  public String process(String s) {
    p.process();
  }

  protected final String log(String s) {
    // logging
  }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM