これを行う 1 つの方法を次に示しますが、最適ではありません。
これは、主にオブジェクトの作成が制限されていないため、最適な方法ではありません。最適な方法であるためには、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
でもあります。このメソッドは、現在の JVM でのコントラクトを保証します。Singleton
また、複数のクラスローダーと複数の 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 */ }
}
JConsole
JMX アプローチを使用することの追加の利点は、アプリケーションの実行中にこれらのインスタンスを非常に簡単に管理できることです。
注:便宜上、内部クラスとして単一のファイルを使用しましたinterfaces
が、問題なく独自のファイルに含めることができます。