【问题标题】:proper way of exposing singleton class through interface通过接口公开单例类的正确方法
【发布时间】:2015-10-05 19:45:08
【问题描述】:

我有一个单例类,它必须作为服务公开给使用接口的其他应用程序。

例如:

public class MySingleSingletonClass{

    private static final MySingleSingletonClass THIS_INSTANCE = new MySingleSingletonClass();

    private MySingleSingletonClass() {}

    public static MySingleSingletonClass getInstance(){
       return THIS_INSTANCE;
    }

    //do other staff
   public int methodA(){
     //some service
   }

}

现在如果我想通过接口暴露这个类的所有服务,这是我的第一次尝试:

public interface MyServiceInterface{
    int methodA();
    MyServiceInterface getInstanceThroughService(); 
}

当 MySingleSingletonClass 实现这个接口时:

public class MySingleSingletonClass implements MyServiceInterface{

    private static final MySingleSingletonClass THIS_INSTANCE = new MySingleSingletonClass();

    private MySingleSingletonClass() {}

    public static MySingleSingletonClass getInstance(){
       return THIS_INSTANCE;
    }

   @Override
   public int methodA(){
     //some service
   }

   @Override
   MyServiceInterface getInstanceThroughService(){
     return MySingleSingletonClass.getInstance();
   }

}

我发现这种实现有两个问题,

首先如果我使用像 spring 这样的框架,并且我尝试获取 MyServiceInterface 类型的 bean,该类将如何实例化?我读到 spring 仍然会使用反射调用班级的私人承包商。这个实例仍然是单例吗?

第二,如果 Spring 已经给了我实例,我看不出使用实例本身调用 getInstanceThroughService() 方法的意义。感觉这个实现有问题。

谢谢

【问题讨论】:

    标签: java spring design-patterns singleton


    【解决方案1】:

    典型的 spring bean 默认是单例的!

    @Service
    public class MySingleSingletonClass{
    
       public int methodA(){...}
    }
    
    @Service
    public class ConsumerA{
       @Autowired
       private MySingleSingletonClass mssc;
    }
    
    @Service
    public class ConsumerB{
       @Autowired
       private MySingleSingletonClass mssc;
    }
    

    在这种情况下,您将拥有 3 个 bean: - 一个 MySingleSingletonClass - 一个消费者A - 一个消费者B

    ConsumerAConsumerB 中的引用 mssc 将指向 MySingleSingletonClass 的相同实例。

    所以你不需要实现标准的单例模式,Spring 会为你做。

    【讨论】:

    • 想象在ConsumerA/ConsumerB中无法访问MySingleSingletonClass,只能通过MyServiceInterface访问服务。在这种情况下将如何处理? - 谢谢你
    • @LeTex: 那么MySingleSingletonClass 必须实现MyServiceInterface 并且两个消费者都将使用@Autowired private MyServiceInterfaces mssc;
    【解决方案2】:

    您可以使用 spring 的工厂方法 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html 告诉 spring 使用 getInstanceThroughService() 获取新实例,然后您将提供相同的缓存实例,从而维护您的单例。

    但是,如果您使用的是 spring,那么您不需要自己维护单例对象。 Spring 会自动执行此操作(当然,除非您的类在同一 jvm/classloader 中的 spring 容器之外使用)。

    【讨论】:

      【解决方案3】:

      Spring 是一个实现称为inversion of control(或IoC)的设计模式的框架。 IoC 的一个应用是允许外部框架配置和实例化应用程序的一部分,这确实是 spring bean 的功能。 Spring bean 允许您使用配置文件配置应用程序资源并在您的应用程序中访问这些资源。

      Singleton(和原型 bean)由 Spring 管理,因此无需自己实现 Singleton 设计模式。您只需要创建一个符合 Spring 的 bean 并在 Spring 配置中声明它。然后,您可以从应用程序上下文中访问它。

      您的 bean 仍然可以像往常一样实现接口,并且您可以在应用程序中使用该接口。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-27
        • 1970-01-01
        • 1970-01-01
        • 2021-05-27
        • 1970-01-01
        • 1970-01-01
        • 2011-05-03
        • 2018-10-07
        相关资源
        最近更新 更多