首页 > 解决方案 > 编译时的工厂模式

问题描述

我正在尝试为这个问题找出正确的设计

我有三个类 Thread、Consumer 和 Event

public class Thread {
    private Consumer _consumer = new Consumer();
}

public class Consumer {
    private someMethod() {
        Event event = new Event();
        // do something with event 
    }
}

在我的“main”中创建了 T 并封装了它的依赖项

Thread t = new Thread();

现在设计已经改变,我们需要多个Consumers 并且每个都应该构造一个不同的Event。代码都是一样的,所以我不需要更改Consumer

我尝试使用泛型来做到这一点,因为看起来这是一种简单而干净的方法。但是,看起来不可能在泛型类型上使用new 。(被 C++ 模板误导)

public class Thread<T extends Event> {
    private Consumer _c = new Consumer<T>();
}

public class Consumer<T extends Event> {
    private someMethod() {
        Event event = new T();
    }
}

我的另一个选择是通过某种编译时工厂

public interface IEventFactory {
    public Event create();
}

public class EventFactory implements IEventFactory{
    public Event create() {
        return new Event1();
    }
}

public class Thread {
    private Consumer _consumer;

    public Thread (IEventFactory _factory) {
        _consumer = new Consumer(_factory);
    }
}

public class Consumer {
    private IEventFactory _factory;

    public C(IEventFactory factory) {
        _factory = factory;
    }

    private someMethod() {
        Event event = _factory.create();
    }
}

这个解决方案在工厂一路向下传递时感觉不那么优雅。有没有更好、更优雅的方法来解决这个问题?

标签: javagenericsdesign-patterns

解决方案


工厂在这里只添加样板。您可以使用方法引用来完成同样的事情:将Event' 构造函数传递给 ' 构造Consumer函数。使用Supplier功能接口来执行此操作。

public class Consumer<T extends Event> {
    private final Supplier<T> eventConstructor;

    public Consumer(final Supplier<T> eventConstructor) {
        this.eventConstructor = eventConstructor;
    }

    private void someMethod() {
        final T event = eventConstructor.get();
    }
}

您可以从以下位置向上传播构造函数Thread

class Thread<T extends Event> {
    private Consumer<T> consumer;

    public Thread(final Supplier<T> eventConstructor) {
        this.consumer = new Consumer<>(eventConstructor);
    }
}

示例用法:

Thread<Event1> thr = new Thread<>(Event1::new);

如果某些事件具有构造函数参数,这也将起作用,例如:

Thread<Event2> thr2 = new Thread<>(() -> new Event2("some default"));

推荐阅读