如何设计一个可以仅由1个类实例化的单例
我想设计一个类,它将以类似于单例的方式存在,该类将有一个主实例,但也可能有多个克隆的主要实例。只有1个类可以创建主实例,其他人都可以创建一个克隆。像这样的东西(c#):如何设计一个可以仅由1个类实例化的单例
class Singleton
{
private static Singleton _mainInstance;
private Singleton() {..}
public void Clone() {..}
public static Singleton MainInstance
{
if (_mainInstance == null)
{
_mainInstance = new Singleton(); // how to secure this for only 1 class?
}
return _mainInstance;
}
}
class MainClass
{
public MainClass()
{
Singleton.MainInstance ....
}
}
MainClass应该是唯一允许实例化单例的类。在C++中,可以通过完全隐藏创建逻辑并将MyClass作为Singleton的朋友来完成。
下面是一个完整的工作实现,演示了两种可能的方法来完成你想要的。
这两种方法都使用工厂概念;由于Singleton
的构造函数是私有的,因此只有嵌套的Factory
类才能创建Singleton
类的新实例。由于嵌套Factory
类本身是私有的,获得工厂实例的唯一方法是通过Singleton.GetFactoryFirstOneWins
方法(“第一个获胜”方法)或Singleton.AssignFactories
方法(“间接分配”方法)。
interface IFactory<T>
{
T CreateInstance();
}
class Singleton
{
class Factory : IFactory<Singleton>
{
public Singleton CreateInstance()
{
// return a clone of _MainInstance
return new Singleton(_MainInstance);
}
}
// *** Begin "First one wins" approach
static IFactory<Singleton> _FactoryFirstOneWins;
public static IFactory<Singleton> GetFactoryFirstOneWins()
{
if (_FactoryFirstOneWins != null)
throw new InvalidOperationException("A factory has already been created.");
return _FactoryFirstOneWins = new Factory();
}
// *** End "First one wins" approach
// *** Begin "Indirect assignment" approach
public static void AssignFactories()
{
MainClass.SingletonFactory = new Factory();
}
// *** End "Indirect assignment" approach
private static readonly Singleton _MainInstance = new Singleton();
public static Singleton MainInstance
{
get { return _MainInstance; }
}
private Singleton()
{
// perform initialization logic
this.SomeValue = 5; // pick some arbitrary number
}
private Singleton(Singleton instance)
{
// perform cloning logic here to make "this" a clone of "instance"
this.SomeValue = instance.SomeValue;
}
public int SomeValue { get; set; }
public void DoSomething()
{
Console.WriteLine("Singleton.DoSomething: " + this.SomeValue);
// ...
}
}
class MainClass
{
private static IFactory<Singleton> _SingletonFactory;
public static IFactory<Singleton> SingletonFactory
{
get { return _SingletonFactory; }
set { _SingletonFactory = value; }
}
public Singleton Singleton { get; private set; }
public MainClass()
{
this.Singleton = SingletonFactory.CreateInstance();
}
public void DoWork()
{
Console.WriteLine("MainClass.DoWork");
this.Singleton.DoSomething();
// ...
}
}
class Program
{
static void Main(string[] args)
{
// you could either use the "First one wins" approach
MainClass.SingletonFactory = Singleton.GetFactoryFirstOneWins();
// or use the "Indirect assignment" approach
Singleton.AssignFactories();
// create two separate MainClass instances
MainClass mc1 = new MainClass();
MainClass mc2 = new MainClass();
// show that each one utilizes a Singleton cloned from Singleton.MainInstance
mc1.DoWork();
mc2.DoWork();
// updating mc1.Singleton.SomeValue does not affect any other instances of MainClass
mc1.Singleton.SomeValue = 7;
mc1.DoWork();
mc2.DoWork();
// updating Singleton.MainInstance.SomeValue affects any new instances of MainClass, but not existing instances
Singleton.MainInstance.SomeValue = 10;
MainClass mc3 = new MainClass();
mc1.DoWork();
mc2.DoWork();
mc3.DoWork();
}
}
感谢您的解决方案。尽管我最终没有使用这种解决方案,但间接分配技巧让我想到了另一种设计解决方案。好主意,谢谢! – kateroh 2010-10-20 18:12:06
你可以简单地在你的类中使用带有私有静态字段的Singleton模式。
像这样:
class Singleton
{
private static Singleton _mainInstance = new Singleton();
private Singleton() { }
public void Clone() {..}
public static Singleton MainInstance
{
return _mainInstance;
}
}
你将有你的存储类的_mainInstance静态字段里面你唯一的实例,就不可能创造任何其他实例。
我在方法和属性中添加了'static'。我知道如何写一个signleton,那不是原来的问题。我希望整个库中只有一个类能够实例化第一个实例。 – kateroh 2010-10-20 16:24:21
单例模式意味着只有一个该类的实例。如果你的类有某种克隆方法,那么每个人都可以克隆这个实例。所以我看不到你的问题。
您的单例执行几乎是正确的,只有_mainInstance
和MainInstance
需要为static
。
我添加了“静态”,这是我的错误。克隆方法与原始问题无关 - 如何使该单例的第一个实例由解决方案中的1和1类创建。所以只有一个输入点 - 你可以通过MainClass获得这个实例,负责创建一个或者唯一的实例,或者你得到null。 – kateroh 2010-10-20 16:27:36
你可以让Singleton成为Main的一个私有内部类,并让Singleton实现一个公开的可见接口,它在任何地方都可见 – codymanix 2010-10-20 16:41:01
但是你的问题没有多大意义。如果Singleton每次都返回相同的实例,为什么只有你的MainClass应该被允许调用它呢?你害怕发生什么? – codymanix 2010-10-20 16:43:12
您可以使用内部的构造函数只有在其装配其他类使一个类实例化的:
class InternalInstantiation {
internal InternalInstantiation() {}
public void Clone() {}
}
class MainClass {
private InternalInstantiation _instance =
new InternalInstantiation();
}
此外,您还可以嵌套在另一个内部类实例化一个类有私有构造函数。
class PrivateInstantiation {
private PrivateInstantiation() { }
public void Clone() {}
public class MainClass {
private PrivateInstantiation _instance =
new PrivateInstantiation();
}
}
您还可以创建私有实例化的类中的主类注入它的一个实例(没有其他类可以使用)方案:
public class MainClass {
internal PrivateInstantiation PrivateInstantiation { get; set; }
public MainClass() {
PrivateInstantiation.CreateAndSet(this);
}
}
class PrivateInstantiation {
private PrivateInstantiation() { }
public void Clone() {}
public static void CreateAndSet(MainClass mc) {
mc.PrivateInstantiation = new PrivateInstantiation();
}
}
请注意,我没有打电话你的班级是一个单身人士,因为Clone
方法的出现似乎并没有使它成为一个单身人士。
什么是单身人士的克隆?同一对象(通过引用)或克隆时具有相同状态的新对象?如果第一,你的问题是自我多余的,如果第二,不要称之为单身...原型可能? – 2010-10-20 16:59:48