我想使用RxJavaPlugins重现RxJava的“静态”注入,如果此类的设计是众所周知的模式,我很想知道!

我所有活动都有一个基本的模型课

import lombok.Getter;

public abstract class BasicEvent {

    @Getter
    private final String id;

    @Getter
    private final long timestamp;

    public BasicEvent() {
        this.id = IDGenerator.BY_COUNTER.generate();
        this.timestamp = TimePlayer.clock().timestamp();
    }
}


上述类的主要缺点是可测试性。我不能更改IDGenerator和TimePlayer。

我认为拥有像RxJavaPlugins这样的第三方类可以帮助我更改测试的元数据生成器

更新。

我一直遵循RxJavaPlugins解决方案来保持模型的创建简单,而不必担心id和时间戳(我称为两个字段元数据),在这里找到了解决方案。

public BasicEvent() {
    this.id = MetaGenerator.idGenerator().generate();
    this.timestamp = MetaGenerator.timePlayer().timestamp();
}


public class MetaGenerator {

    public static IDGenerator idGenerator() {
        // DGenerator.BY_COUNTER is the default value
        return MetaGeneratorPlugins.onIDGenerator(IDGenerator.BY_COUNTER);
    }

    public static TimePlayer timePlayer() {
        return MetaGeneratorPlugins.onTimePlayer(TimePlayer.realtime);
    }
}

public class MetaGeneratorPlugins {

    private static Function<? super TimePlayer, ? extends TimePlayer> onTimePlayerHandler;
    private static Function<? super IDGenerator, ? extends IDGenerator> onIDGeneratorHandler;

    public static void setTimePlayerHandler(@Nullable Function<? super TimePlayer, ? extends TimePlayer> handler) {
        onTimePlayerHandler = handler;
    }

    public static void setIDGeneratorHandler(@Nullable Function<? super IDGenerator, ? extends IDGenerator> handler) {
        onIDGeneratorHandler = handler;
    }

    //return the default value or the value returned by the handler
    public static TimePlayer onTimePlayer(@Nonnull TimePlayer defaultScheduler) {
        if (onTimePlayerHandler == null) {
            return defaultScheduler;
        }
        return apply(onTimePlayerHandler, defaultScheduler);
    }

    public static IDGenerator onIDGenerator(@Nonnull IDGenerator defaultScheduler) {
        if (onIDGeneratorHandler == null) {
            return defaultScheduler;
        }
        return apply(onIDGeneratorHandler, defaultScheduler);
    }

    private static <T, R> R apply(@Nonnull Function<T, R> f, @Nonnull T t) {
        return f.apply(t);
    }
}


现在,在我的测试中,我可以通过调用MetaGeneratorPlugins来更改此MetaGenerator的实现。

MetaGeneratorPlugins.setIDGeneratorHandler(IDGenerator.INCREMENTAL);
MetaGeneratorPlugins.setTimePlayerHandler(TimePlayer.simulated);


RxJavaPlugins就是这样工作的,我从他们的解决方案中得到了启发,

现在,我的模型创建很简单,并且可以用于生产和测试。

最佳答案

更改BasicEvent的设计,以便以更可测试的方式绑定idtimestamp

介绍一个“ stamper”界面:

public interface Stamper {
  String generateId();
  long   generateTimestamp();
}


“默认”实现如下所示:

public RealTimeStamper implements Stamper {
  @Override public String generateId() {
    return IDGenerator.BY_COUNTER.generate();
  }
  @Override public long generateTimestamp() {
    return TimePlayer.clock().timestamp();
  }
}


提供Stamper的可测试实现。然后使用您使用的任何依赖项注入过程绑定适当的实现。

public abstract class BasicEvent {
  static Stamper stamper;
  ...
  public BasicEvent() {
    this.id = stamper.generateId();
    this.timestamp = stamper.generateTimestamp();
  }
}


可以手动或使用依赖项注入框架来注入stamper字段。

09-30 11:23