.NET 3.5 では、シングルトン インターフェイスを作成したいと思います。
interface ISingleton <T>
{
public static T Instance {get;}
}
もちろんそれはうまくいきませんが、私が望むものです。助言がありますか?
編集:すべてのシンゲルトンがクラス型のインスタンスという名前の静的プロパティを持つことを知ってもらいたいだけです。それは常にそこにあります。インターフェイスは、これを明示的に表現する方法です。
.NET 3.5 では、シングルトン インターフェイスを作成したいと思います。
interface ISingleton <T>
{
public static T Instance {get;}
}
もちろんそれはうまくいきませんが、私が望むものです。助言がありますか?
編集:すべてのシンゲルトンがクラス型のインスタンスという名前の静的プロパティを持つことを知ってもらいたいだけです。それは常にそこにあります。インターフェイスは、これを明示的に表現する方法です。
私の知る限り、インターフェイスは実際には存在しないため、シングルトンになることはできません。インターフェイスは、実装が従わなければならない契約です。そのため、実装はシングルトンにすることができますが、インターフェイスはできません。
シングルトンが非常に使いすぎているという他のポスターに同意しますが、あなたの質問に対する可能な解決策は、派生シングルトンの型パラメーターを持つ抽象基本クラスを提供することです。
public abstract class Singleton<T> where T : Singleton<T>
{
private static T _instance;
public static T Instance
{
get { return _instance; }
protected set { _instance = value; }
}
}
Singleton から派生するすべてのクラスには、正しい型の静的 Instance プロパティがあります。
public class MySingleton : Singleton<MySingleton>
{
static MySingleton()
{
Instance = new MySingleton();
}
private MySingleton() { }
}
ただし、このようなものを使用する前に、シングルトンが必要かどうか、または通常の静的クラスを使用したほうがよいかどうかを実際に検討する必要があります。
あなたの質問に接する意見を提供するだけなので、この回答をWikiにしました。
個人的には、シングルトンは使いすぎだと思います。IMO は実際にはかなりまれなユース ケースです。ほとんどの場合、静的クラスがユース ケースにはるかに適しています。それ以外の場合は、工場で作成された不変オブジェクトが最良の選択です。実際のシングルトンは、人々が考えるよりもはるかにまれです。
シングルトンのすべての使用を非常に慎重に検討し、正当化することを実際に望んでいるため、これの一般的なパターンを説明するためのインターフェイスはありません。
あなたの質問ではないことはわかっていますが、インターフェイスが必要なシングルトンはいくつありますか? これは私には悪い設計のような匂いがします.なぜこれらのクラスがインスタンスではなくシングルトンであるべきなのかを明確に説明できますか? あなたの答えがメモリである場合は、アプリケーションを考えすぎることをお勧めします。本当に心配している場合は、flyweight パターン (または単純なファクトリ パターン) を調べてください。質問に直接答えなくて申し訳ありませんが、これは素晴らしいアイデアとは思えません。
すべてのシンゲルトンがクラス型の Instance という名前の静的プロパティを持つことを知ってもらいたいだけです。それは常にそこにあります。インターフェイスは、これを明示的に表現する方法です。
代わりに単体テストを作成してください。
それに加えて、あなたが述べているように、このインターフェースと実装クラスをどのように使用しますか?
Factory スタイルのインターフェースを試すことができます
interface ISingletonFactory<T>
{
public T Instance {get;}
}
public class SingletonFactory: ISingletonFactory<Singleton>
{
public Singleton Instance {get { return Singleton.Instance;}}
}
public class Singleton
{
private Singleton foo;
public static Singleton Instance { get { return foo; } }
}
指摘されたように、あなたはこれを行うことができず、あなたがすべきでない理由があります。
私が過去に実装したメソッドは、インターフェイスと、インターフェイスを実装する抽象基本クラスを作成します。これは次のようになります。
public interface IMyCompanySetting
{
XmlNode Serialize();
IMyCompanySetting Deserialize(XmlNode pattern);
string SettingName { get; }
文字列キー{取得; }オブジェクトSettingValue{get; セットする; } SettingScope Scope {get; セットする; }}
public abstract class MyCompanySettingBase : IMyCompanySetting
{
public MyCompanySettingBase() {}
public MyCompanySettingBase(XmlNode pattern)
{
Deserialize(pattern);
}
#region IMyCompanySetting Members
public abstract XmlNode Serialize();
public abstract IMyCompanySetting Deserialize(XmlNode pattern);
public abstract string SettingName{ get; }
public abstract string Key { get; }
public abstract SettingScope Scope{ get; set; }
public abstract object SettingValue{ get; set; }
#endregion
public static XmlNode WrapInSettingEnvelope(XmlNode innerNode, IMyCompanySetting theSetting)
{
// Write the top of the envelope.
XmlTextWriter xtw = null;
MemoryStream theStream = OpenSettingEnvelope(theSetting, ref xtw);
// Insert the message.
xtw.WriteNode(new XmlTextReader(innerNode.OuterXml, XmlNodeType.Element, null), true);
// Close the envelope.
XmlNode retNode = CloseSettingEnvelope(xtw, theStream);
return retNode;
}
public static MemoryStream OpenSettingEnvelope(IMyCompanySetting theSetting, ref XmlTextWriter theWriter)
{
MemoryStream theStream = new MemoryStream();
theWriter = new XmlTextWriter(theStream, Encoding.ASCII);
System.Type messageType = theSetting.GetType();
string[] fullAssembly = messageType.Assembly.ToString().Split(',');
string assemblyName = fullAssembly[0].Trim();
theWriter.WriteStartElement(theSetting.SettingName);
theWriter.WriteAttributeString("type", messageType.ToString());
theWriter.WriteAttributeString("assembly", assemblyName);
theWriter.WriteAttributeString("scope", ConfigurationManager.ScopeName(theSetting.Scope));
return theStream;
}
public static XmlNode CloseSettingEnvelope(XmlTextWriter xtw, MemoryStream theStream)
{
XmlDocument retDoc = new XmlDocument();
try
{
// Close the envelope.
xtw.WriteEndElement();
xtw.Flush();
// Return the node.
string xmlString = Encoding.ASCII.GetString(theStream.ToArray());
retDoc.LoadXml(xmlString);
}
catch (XmlException)
{
string xmlString = Encoding.ASCII.GetString(theStream.ToArray());
Trace.WriteLine(xmlString);
retDoc.LoadXml(@"<error/>");
}
catch (Exception)
{
retDoc.LoadXml(@"<error/>");
}
return retDoc.DocumentElement;
}
}
実装クラス間のコントラクトとして定義するインターフェイスの OOP の古典的な概念を考えると、静的メソッドなどをそれに追加することはできません。できれば、クラスの部分的な実装と拡張クラスに要求される他の部分がある抽象クラスに似たもので終わることになります。