代码之家  ›  专栏  ›  技术社区  ›  Paul-Jan

带有公共(单实例)构造函数的单实例

  •  3
  • Paul-Jan  · 技术社区  · 17 年前

    作为一个练习,我将把大型的、久经战斗考验的Delphi框架的一些部分翻译成C。

    此框架中包含一个通用的单例父类。当然,在C中实现一个singleton是相当容易的(甚至还有一篇jon skeet文章,我还想知道更多),但是我们的delphi singleton在模式上有一个稍微不同的看法:与发布“instance”属性/方法不同,它有一个“fake”构造函数,它总是返回相同的实例。这种方法的基本特征是 singleton类的用户不知道他正在处理一个singleton : 据他们所知,他们只是构造任何旧类并从中请求一些信息。

    我想在C中完成同样的事情(作为练习,所以它不必是生产质量代码,邪恶的黑客很好),但到目前为止我失败了。

    有什么简单的建议吗 myInstance = new MyClass(); 总是返回同一个实例是最受欢迎的!


    附加信息

    • 我们讨论的是框架提供的单例模式的便利实现。它不必非得是父类,但它也必须帮助开发人员创建自己的单例类。要求他们手动将所有方法调用重定向到单个实例不会使他们欣喜若狂。-)

    • 我对讨论这是否是处理单身汉的正确方法并不感兴趣,因为现在我只对C调整的更精细的艺术感兴趣。

    7 回复  |  直到 16 年前
        1
  •  2
  •   devios1    17 年前

    据我所知,这不能真正做到,因为C是如何处理对象实例的。为了调用构造函数,必须实际创建实例,并且不能从构造函数“返回”另一个对象。

    我能想到的最好的事情(除了使用工厂方法)是将类内部视为一个单例,并创建“虚拟”实例,这些实例在创建时都只指向原始实例。例如,在您的构造函数中,您将检查singleton是否已经初始化,如果没有,则初始化它,然后基本上将每个实例的方法和属性代理回singleton。

    在这个实现中,singleton甚至不必是同一个类,但是如果您想保持包含内容的话,可以这样做。

    更新: 这种方法的一个缺点是尽管每个实例 表现 作为单一实例,它仍然有自己的对象引用,因此您可能还希望重写 Equals() 用于平等比较。

        2
  •  7
  •   George Mauer    17 年前

    你可以做一个代理(编辑:正如汤姆在下面指出的,正确的设计模式是单态的):

    public class MyClass {
      MyActualClass _actual;
      public MyClass() {
        _actual = MyActualClass. Instance;
      }
      public DoStuff() {
        _actual.DoStuff();
      }
    }
    
    internal class MyActualClass {
      private MyActualClass {
      }
      public DoStuff() {
        ...
      }
      MyActualClass _instance;
      public static Instance {
        get {
           if(_instance == null)
             _instance = new MyActualClass()
           return _instance;
        }
      }
    }
    

    public static void Main() {
      var my1 = new MyClass();
      var my2 = new MyClass();   
    }
    

    MY1!=my2,但my1.dostuff()调用与my2.dostuf()相同的方法实例 如果只对一个接口进行编程,这将进一步简化。

    编辑:通过使_actual protected internal和重写myclass.equals(object obj)来检查这一点,可以部分解决相等问题。_actual==obj._actual

        3
  •  4
  •   tstojecki    17 年前

    我相信单态模式会给你所需要的:

    单态给了我们在单态中如此珍视的状态的奇异性,但是没有伴随它而来的所有静态头痛。”

    这里更多: http://jeremyjarrell.com/archive/2008/04/21/88.aspx

        4
  •  0
  •   leppie    17 年前

    我想你可以用远程处理来处理一些事情。

    更新:

    更好的方法是在结构或轻量级类中包装适当的单例类。

        5
  •  0
  •   Bombe    17 年前

    将singleton创建为静态成员,并使所有方法都访问单个静态实例。

    class SingletonWrapper {
    
        private static RealSingleton instance = new RealSingleton();
    
        public void methodA() {
            instance.methodA();
        }
    
        public String getA() {
            return instance.getA();
        }
    
    }
    

    (这实际上是Java代码,但C是足够相似的,我想。:)

        6
  •  0
  •   Karl    17 年前

    我看不出您怎么做,因为构造函数不使用返回语句。您可以将所有相关链接克隆到singleton,但是它会有局部变量的本地副本,并且非常混乱。

    相反,让构造函数检查singleton是否被实例化,如果它已经被实例化,则抛出异常,或者向正在使用旧样式代码的开发人员记录警告。

        7
  •  0
  •   eaanon01    17 年前

    用一个静态函数返回一个使用new关键字的对象怎么样?

    static private m_obj my_obj;
    static private bool my_new_obj;
    static public m_obj create_m_obj()
    {
        if (my_new_obj == false)
        {
            my_new_obj = true;
            my_obj = new my_obj();
        }
        return my_obj;
    }
    

    如果我没弄错的话,你很容易完全控制物体的创造。