さて、あなたはJavaについて話していると思います。Java 言語自体は、Singleton パターン IMO を定義する適切な方法を提供していません。そのため、そのようなコードで特定のパターンを使用したい場合は、AspectJ を使用して拡張します。
AspectJ を使用すると、コンストラクターへのすべての呼び出しを実際に「キャッチ」して、常に同じオブジェクトを返すようにすることができるため、何があってもシングルトンを持つことができます。
必要に応じて、AspectJ のプロトコル コードを次に示します。
package singleton.aspectJ;
import java.util.Hashtable;
import java.util.Map;
import org.aspectj.lang.annotation.AdviceName;
/**
* Defines the general behavior of the Singleton design pattern.
*
* Each concrete sub-aspect of SingletonProtocol defines the Singleton
* property for one or more types.
*
* The sub-aspect defines two things: <ol>
*
* <li> what types are <i>Singleton</i> <br>
*
* <li> what classes can access the <i>Singleton</i>'s constructor (if any)
* despite its property
* </ol>
*
* for this implementation we choose to illustrate that it is not necessary
* to provide a factory method for accessing the <i>Singleton</i>
* instance (like <i>getSingleton()</i>). The regular
* constructor may be used instead.
*
* @author Jan Hannemann
* @author Gregor Kiczales
* @author Pedro Martins
* @version 1.1.1, 21/11/2011
*/
public abstract aspect SingletonProtocol {
/**
* stores the <i>Singleton</i> instances
*/
private Map<Class<Object>, Object> singletonsTable =
new Hashtable<Class<Object>, Object>();
/**
* Defines the <i>Singleton</i> role.
*/
protected interface SingletonInterface{}
/**
* Placeholder for exceptions to the <i>Singleton</i>'s constructor
* protection. For example, non-singleton subclasses may need to
* access the protected constructor of the <i>Singleton</i> normally.
*
* An alternative implementation would be to define an interface
* for singleton exceptions similar to the one above.
*/
protected pointcut protectionExclusions();
private pointcut singletonInstantiator() : call ((SingletonInterface+).new(..)) && !protectionExclusions();
/**
* Protects the <i>Singleton</i>'s constructor. Creates the unique
* instance on demand and returns it instead of a new object.
*
* @return the singleton instance
*/
@SuppressWarnings("unchecked")
@AdviceName("newCatcher")
Object around() : singletonInstantiator(){
Class<Object> singleton = thisJoinPoint.getSignature().getDeclaringType();
if(!singletonsTable.containsKey(singleton))
singletonsTable.put(singleton, proceed());
return singletonsTable.get(singleton);
}
}
そして、ここに例があります:
package singleton.aspectJ;
public aspect SingletonInstance extends SingletonProtocol{
declare parents: God implements SingletonInterface;
protected pointcut protectionExclusions():
call((Canaanites+).new(..));
}
この場合、God は SingletonInterface を実装しているため、シングルトンです。別のクラス Cannnites は神の子ですが、例外として追加されているため、シングルトンではありません。驚くべきことに、これは神のコードであり、その子です。
public class God {
//Code specific to this class's objective
}
public class Caanites extends God {
//Code specific to this class's objective
}
ご覧のとおり、驚くべきことに、God and Caanites クラスにはパターン コードがありません。私が助けてくれることを願っています。