这是一种方法,但它不是最佳的:
这不是最好的方法,主要是因为对象的创建不受限制,因为它是最佳的MyObject
构造函数需要private
并且实例需要在其自身上。
初始化static {}
块中的引用是一种更好的做法,inline
因为您可以Exceptions
在初始化引用之前处理其他逻辑,这是一种最佳做法。
但这是你在很多快速而肮脏的代码中看到的,这些代码大多是不正确的,因为下面的原因在更好的解决方案中。
class Engine {
private static final MyObject OBJ1;
private static final MyObject OBJ2;
static
{
OBJ1 = new MyObject();
OBJ2 = new MyObject();
}
public MyObject getObj(final int param)
{
switch (param)
{
case 1:
return Engine.OBJ1;
case 2:
return Engine.OBJ2;
default:
throw new IllegalArgumentException(String.format("%d is not a valid object id", param));
}
}
这是一个更好的方法:
这更好,因为它隐藏了实现。拥有一个内部类允许您创建类public
,但创建构造函数private
并控制对MyObject
实例创建的访问。
public class Engine
{
private static final MyObject OBJ1;
private static final MyObject OBJ2;
static
{
OBJ1 = new MyObject1();
OBJ2 = new MyObject2();
}
public MyObject getObj(final int param)
{
switch (param)
{
case 1:
return Engine.OBJ1;
case 2:
return Engine.OBJ2;
default:
throw new IllegalArgumentException(String.format("%d is not a valid object id", param));
}
}
public static class MyObject1 implements MyObject { private MyObject1() {} }
public static class MyObject2 implements MyObject { private MyObject2() {} }
}
最佳长期解决方案,此时使用最现代的成语:
这种解决方案更冗长,但在执行 a 的语义方面也是最正确Singleton
的。该方法保证Singleton
合约在当前 JVM 中。它还可以扩展到多个类加载器和多个 JVM,但允许您将其更改MBeanServer
为不同的实现,并在不更改任何其他代码的情况下远程查找引用。为简单起见,此处有意忽略 DI/IoC。
import javax.management.InstanceAlreadyExistsException;
import javax.management.JMX;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;
public class Engine
{
private static final MyObject OBJ1;
private static final MyObject OBJ2;
static
{
try
{
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName on1 = new ObjectName("com.example:type=MyObject1");
final ObjectName on2 = new ObjectName("com.example:type=MyObject2");
OBJ1 = JMX.newMBeanProxy(mbs, on1, MyObject.class);
OBJ2 = JMX.newMBeanProxy(mbs, on2, MyObject.class);
}
catch (MalformedObjectNameException e) { throw new RuntimeException(e); }
}
public MyObject getObj(final int param)
{
switch (param)
{
case 1:
return Engine.OBJ1;
case 2:
return Engine.OBJ2;
default:
throw new IllegalArgumentException(String.format("%d is not a valid object id", param));
}
}
public static class MyObject1 implements MyObjectMBean
{
static
{
try
{
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName on1 = new ObjectName("com.example:type=MyObject1");
mbs.registerMBean(new MyObject1(), on1);
}
catch (MalformedObjectNameException e) { throw new RuntimeException(e); }
catch (NotCompliantMBeanException e) { throw new RuntimeException(e); }
catch (InstanceAlreadyExistsException e) { throw new RuntimeException(e); }
catch (MBeanRegistrationException e) { throw new RuntimeException(e); }
}
private MyObject1() { /* your interface implementations go here */ }
}
public static class MyObject2 implements MyObjectMBean
{
static
{
try
{
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
final ObjectName on1 = new ObjectName("com.example:type=MyObject2");
mbs.registerMBean(new MyObject2(), on1);
}
catch (MalformedObjectNameException e) { throw new RuntimeException(e); }
catch (NotCompliantMBeanException e) { throw new RuntimeException(e); }
catch (InstanceAlreadyExistsException e) { throw new RuntimeException(e); }
catch (MBeanRegistrationException e) { throw new RuntimeException(e); }
}
private MyObject2() { /* your interface implementations go here */ }
}
private static interface MyObjectMBean extends MyObject { /* mbean specific methods go here */ }
private static interface MyObject { /* your interface methods go here */ }
}
使用 JMX 方法的额外好处是您可以JConsole
非常轻松地管理这些实例,而在应用程序运行时,您可以免费获得!
注意:为了方便起见,我使用了带有 as 内部类的单个文件interfaces
,它们可以在自己的文件中没有问题。