首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Spring3注释实现一个简单的工厂模式

使用Spring3注释实现一个简单的工厂模式
EN

Stack Overflow用户
提问于 2011-06-18 03:27:14
回答 14查看 128.2K关注 0票数 73

我想知道如何使用Spring3注释实现简单的工厂模式。我在文档中看到,您可以创建调用工厂类并运行工厂方法的bean。我想知道是否可以只使用注释。

我有一个控制器,它当前调用

代码语言:javascript
复制
MyService myService = myServiceFactory.getMyService(test);
result = myService.checkStatus();

MyService是一个具有名为checkStatus()的方法的接口。

我的工厂类看起来像这样:

代码语言:javascript
复制
@Component
public class MyServiceFactory {

    public static MyService getMyService(String service) {
        MyService myService;

        service = service.toLowerCase();

        if (service.equals("one")) {
            myService = new MyServiceOne();
        } else if (service.equals("two")) {
            myService = new MyServiceTwo();
        } else if (service.equals("three")) {
            myService = new MyServiceThree();
        } else {
            myService = new MyServiceDefault();
        }

        return myService;
    }
}

MyServiceOne类如下所示:

代码语言:javascript
复制
@Autowired
private LocationService locationService;

public boolean checkStatus() {
      //do stuff
}

当我运行这段代码时,locationService变量总是空的。我认为这是因为我自己在工厂中创建对象,并且自动装配没有发生。有没有一种方法可以添加注释来使其正确工作?

谢谢

EN

回答 14

Stack Overflow用户

回答已采纳

发布于 2011-06-18 03:35:04

您是对的,通过手动创建对象,您不会让Spring执行自动装配。也可以考虑使用Spring管理您的服务:

代码语言:javascript
复制
@Component
public class MyServiceFactory {

    @Autowired
    private MyServiceOne myServiceOne;

    @Autowired
    private MyServiceTwo myServiceTwo;

    @Autowired
    private MyServiceThree myServiceThree;

    @Autowired
    private MyServiceDefault myServiceDefault;

    public static MyService getMyService(String service) {
        service = service.toLowerCase();

        if (service.equals("one")) {
            return myServiceOne;
        } else if (service.equals("two")) {
            return myServiceTwo;
        } else if (service.equals("three")) {
            return myServiceThree;
        } else {
            return myServiceDefault;
        }
    }
}

但我认为它的整体设计相当糟糕。拥有一个通用的MyService实现并将one/two/three字符串作为额外参数传递给checkStatus()不是更好吗?你想实现什么目标?

代码语言:javascript
复制
@Component
public class MyServiceAdapter implements MyService {

    @Autowired
    private MyServiceOne myServiceOne;

    @Autowired
    private MyServiceTwo myServiceTwo;

    @Autowired
    private MyServiceThree myServiceThree;

    @Autowired
    private MyServiceDefault myServiceDefault;

    public boolean checkStatus(String service) {
        service = service.toLowerCase();

        if (service.equals("one")) {
            return myServiceOne.checkStatus();
        } else if (service.equals("two")) {
            return myServiceTwo.checkStatus();
        } else if (service.equals("three")) {
            return myServiceThree.checkStatus();
        } else {
            return myServiceDefault.checkStatus();
        }
    }
}

这仍然是糟糕的设计,因为添加新的MyService实现也需要修改MyServiceAdapter (违反SRP)。但这实际上是一个很好的起点(提示:映射和策略模式)。

票数 45
EN

Stack Overflow用户

发布于 2016-09-07 12:58:20

下面的方法对我很有效:

该接口由您的逻辑方法和附加标识方法组成:

代码语言:javascript
复制
public interface MyService {
    String getType();
    void checkStatus();
}

一些实现:

代码语言:javascript
复制
@Component
public class MyServiceOne implements MyService {
    @Override
    public String getType() {
        return "one";
    }

    @Override
    public void checkStatus() {
      // Your code
    }
}

@Component
public class MyServiceTwo implements MyService {
    @Override
    public String getType() {
        return "two";
    }

    @Override
    public void checkStatus() {
      // Your code
    }
}

@Component
public class MyServiceThree implements MyService {
    @Override
    public String getType() {
        return "three";
    }

    @Override
    public void checkStatus() {
      // Your code
    }
}

工厂本身如下所示:

代码语言:javascript
复制
@Service
public class MyServiceFactory {

    @Autowired
    private List<MyService> services;

    private static final Map<String, MyService> myServiceCache = new HashMap<>();

    @PostConstruct
    public void initMyServiceCache() {
        for(MyService service : services) {
            myServiceCache.put(service.getType(), service);
        }
    }

    public static MyService getService(String type) {
        MyService service = myServiceCache.get(type);
        if(service == null) throw new RuntimeException("Unknown service type: " + type);
        return service;
    }
}

我发现这样的实现更容易,更整洁,更具可扩展性。添加新的MyService就像创建另一个实现相同接口的spring bean一样简单,而不需要在其他地方做任何更改。

票数 116
EN

Stack Overflow用户

发布于 2019-03-08 17:33:19

下面是DruidKuma的回答

使用自动连接的构造器对他的工厂进行少量重构:

代码语言:javascript
复制
@Service
public class MyServiceFactory {

    private static final Map<String, MyService> myServiceCache = new HashMap<>();

    @Autowired
    private MyServiceFactory(List<MyService> services) {
        for(MyService service : services) {
            myServiceCache.put(service.getType(), service);
        }
    }

    public static MyService getService(String type) {
        MyService service = myServiceCache.get(type);
        if(service == null) throw new RuntimeException("Unknown service type: " + type);
        return service;
    }
}
票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6390810

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档