3

シングルトン設計パターンに従って、「アプリケーション」全体でシングルトン クラスのインスタンスは 1 つしか存在できません。ただし、この定義では、Singleton クラス自体が 1 つのクラスローダーによって 1 回ロードされることを前提としています。ただし、理論上のマルチ VM 環境では、同じ Singleton クラスが複数のクラスローダーによってロードされる可能性があります。

開発者は、マルチ VM 環境全体で単一のインスタンスのみを使用できるようにするにはどうすればよいでしょうか? 単一のクラスローダーのみを介してクラスローディングが確実に行われるようにする方法はありますか?

4

3 に答える 3

4

簡潔な答え?管理されていない環境ではできません。これはシングルトン パターンの誤謬です。通常の環境で強制することは実際には不可能です。考えてみてください。クラス オブジェクトはクラス ローダーのコンテキストに存在し、同じ VM に複数のオブジェクトが存在する可能性があります。また、同じノード内に複数の VM が存在する場合があります。また、複数のノードを同じアプリケーションの一部にすることができます。もちろん、それらがシングルトンとして実装されている場合、これらのクラスオブジェクトのそれぞれがクラスの単一のインスタンスを作成しますが、(潜在的に)多くのクラスオブジェクトが存在する可能性があります。

Oleg Mikheev の回答で述べたように、Java EE 仕様の最近のバージョンには、シングルトン セッション Bean の規定があります。私はそれらの実装の詳細に精通していませんが、それらが本当に本当にシングルトンなのか、つまりクラスター化されたアプリケーション全体に存在する単一のインスタンスなのか、それとも異なるアプリケーションに複数のインスタンスが存在する論理的な抽象化にすぎないのか疑問に思っています。ノード。

于 2013-01-28T22:47:08.810 に答える
0

さて、あなたは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 クラスにはパターン コードがありません。私が助けてくれることを願っています。

于 2013-01-28T22:55:14.233 に答える
0

オブジェクト指向プログラミングのアンチパターンであるシングルトンを取り除くようにしてください。代わりに、オブジェクトを構成可能にして、コンストラクターで依存関係を渡します。これが問題の根本原因を解決する方法であり、クラスのインスタンスが 1 つだけあることを常に確認できます。

于 2013-01-29T15:23:02.617 に答える