使用Spring配置Abstract Factory的实现类 [英] Configure Implementation Class of Abstract Factory with Spring

查看:67
本文介绍了使用Spring配置Abstract Factory的实现类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的应用程序,我有一个Scale接口和多个实现此接口的类,例如NormalizedScaleLogScale等.在我的一个服务中,我需要创建许多秤,并且我想使用Spring定义应创建的Scale实现.我将如何实施这样的事情?

For my application, I have a Scale interface and multiple classes implementing this interface, for example NormalizedScale, LogScale, etc. In one of my Services, I need to create many Scales, and I want to use Spring to define which implementation of the Scale it should create. How would I implement something like this?

-

我正在考虑创建一个工厂ScaleFactory,就像在抽象工厂模式"中一样,我可以调用ScaleFactory.getScale()以获得我在Spring XML中配置的任何实现的Scale:

I was thinking to create a factory ScaleFactory, like in the Abstract Factory Pattern, which I could call ScaleFactory.getScale() to get a Scale of whichever implementation I configured in the Spring XML:

class ScaleFactory {
    Class<? extends Scale> scaleImplClass;
    public static Scale getScale() {
        return scaleImplClass.newInstance();
    }
}


Scale myScale = ScaleFactory.getScale();

但是使用这种方法,我如何配置ScaleFactory应该从Spring XML中使用哪种实现?

But with that approach, how could I configure which implementation the ScaleFactory should use from Spring XML?

-

另一种选择是将ScaleFactory设为@Service,然后将ScaleFactory自动连接到我的服务中:

An alternative would be to make the ScaleFactory a @Service, and then autowire the ScaleFactory into my service:

@Autowired
ScaleFactory scaleFactory;

...

Scale myScale = scaleFactory.getScale();

然后,我可以在ScaleFactory中使用自动装配的属性来定义scaleImplClass.但这似乎很奇怪,因为我的工厂也是服务,而且我有该工厂的实例.

Then I can use an autowired property in the ScaleFactory to define the scaleImplClass. But that seems weird because my Factory is also a Service and I have an instance of that factory.

-

另一种方法是在我的 service 中具有Class scaleImplementationClass属性,而不是ScaleFacotry并像这样使用ScaleFactory:

Another approach would be to have the Class scaleImplementationClass property in my service instead of the ScaleFacotry and use the ScaleFactory like so:

@Value("${scaleImplementationClass}")
Class scaleImplementationClass

...

Scale myScale = ScaleFactory.getScale(scaleImplementationClass);

但是那时工厂是没有意义的,因为我也可以很好地运行scaleImplementationClass.newInstance().

But then the factory is quite pointless because I could also just as well run scaleImplementationClass.newInstance().

推荐答案

有两种不同的类似Spring的方式可以处理此问题.我个人追求的方法看起来像这样:

There are a couple of different Spring-like ways you can handle this. The approach I have personally gone for looks a bit like this:

public interface ScaleFactory {

    public Scale newInstance();
    public String type();

}

public class FirstScaleFactory implements ScaleFactory {

    public Scale newInstance() {
        return new FirstScale();
    }

    public String type() {
        return "first";
    }    

}

public class SecondScaleFactory implements ScaleFactory {

    public Scale newInstance() {
        return new SecondScale();
    }

    public String type() {
        return "second";
    }    

}

public class ScaleManager {

    private final Map<String, ScaleFactory> factories;

    @Autowired
    public ScaleManager(List<ScaleFactory> factories) {
        this.factories = factories.stream()
            .collect(Collectors.toMap(f -> f.type(), Function::identity));
    }

    public Scale newInstance(String type) {
        return Optional.ofNullable(factories.get(type))
            .map(factory -> factory.newInstance())
            .orElseThrow(IllegalArgumentException::new);
    }

}

使用这种方法,您的ScaleManager是标准的Spring bean,可以将其连接到需要scale实例的任何类中.在初始化时,它将获取在Spring上下文中定义的所有ScaleFactories,并将它们自动连接为List<ScaleFactory>,然后将其转换为Map(其中ScaleFactory类型为键).这样可以避免担心Scale的类名,并使您能够在以后更改它们(只要保持type键一致)"

With this approach, your ScaleManager is a standard Spring bean that can be wired into any class that needs a scale instance. At initialization time, it gets all ScaleFactories that are defined in the Spring context, and autowires them in as a List<ScaleFactory>, which is then converted to a Map (where the ScaleFactory type is the key). This avoids you needing to worry about class names of Scale, and gives your the ability to change them later (as long as you keep the type key consistent)`

您的ScaleFactory实现然后可以执行他们需要做的任何事情.例如,如果您知道一种不可变的Scale类型,则可以让工厂每次都返回相同的实例.另外,您可以让每次调用都返回一个单独的实例-Scale的实例取决于实现相关的工厂.

Your ScaleFactory implementations can then do whatever they need to do. For example, if you have one type of Scale that you know is immutable, you can have the factory return the same instance every time. Alternatively you can have every invocation return a separate instance - the instantiation of the Scale is up to the implementation-dependent factory.

这篇关于使用Spring配置Abstract Factory的实现类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆