Oop Don';静态成员使类本身成为(全局)对象?

Oop Don';静态成员使类本身成为(全局)对象?,oop,class,design-patterns,singleton,static-members,Oop,Class,Design Patterns,Singleton,Static Members,每次我遇到singleton模式的实现或任何静态类(即(几乎)只有静态成员的类)时,我都想知道这是否真的是一种黑客行为,因此严重滥用类和实例的原则,只是为了设计单个对象,而不是设计类和创建单个实例。在我看来,类的静态成员通常试图向类中添加一些他们实际上不应该拥有的特性,这些特性使它们自己成为对象 但这样实现单个对象真的很理想吗? 或者,您的看法完全不同,不认为这样的静态类或单例与实际对象有任何共同之处吗?假设我有一个具有单个配置文件的应用程序。如果我的语言不支持类外的全局函数(如Java或C#)

每次我遇到singleton模式的实现或任何静态类(即(几乎)只有静态成员的类)时,我都想知道这是否真的是一种黑客行为,因此严重滥用类和实例的原则,只是为了设计单个对象,而不是设计类和创建单个实例。在我看来,类的静态成员通常试图向类中添加一些他们实际上不应该拥有的特性,这些特性使它们自己成为对象

但这样实现单个对象真的很理想吗?
或者,您的看法完全不同,不认为这样的静态类或单例与实际对象有任何共同之处吗?

假设我有一个具有单个配置文件的应用程序。如果我的语言不支持类外的全局函数(如Java或C#),我将如何在不使用“单例”的情况下创建对该文件进行操作的函数

在我看来,实现这一目标的唯一真正途径是开设一门单身课程。使用单例模式,您也不需要传递指向对象的指针,因为您可以使用静态方法再次获取它


我不认为这违反了任何OO原则。用另一种方式,比如将配置函数放在另一个不处理配置的类中(比如“实用程序”类),更违反了OO原则。

静态成员实际上只是全局成员的名称空间,是的。这没什么错;名称空间很好,全局是完成某些任务最干净的方法

单例可能更有趣(按需加载…),但它们是一个类似的构造(是的,您可以将静态成员视为由编译器管理的匿名单例)


与大多数事物一样,这些工具也有自己的位置,只有理论家才会担心它们是否“适合”特定的意识形态。

根据您的语言,类是对象。在ruby和java中,它们是一流的;在python中,我不记得(类型的子类?)

在java中,您无法避免将内容放在类上。这意味着您有时必须像使用名称空间和模块一样使用类。数学上的许多静态方法就是一个很好的例子。我要说的是,让这些方法是静态的,可以充分利用糟糕的情况


我认为拥有静态属性是否“肮脏”在很大程度上取决于上下文。您真正应该寻找的是适当的封装:如果您可以在代码的概念空间中绘制一条曲线并说“这一边的一切都不需要知道那一边的任何事情,除了曲线上的界面。

您可以从性能和内存的角度来查看它。例如,在以下代码中:

public class StringUtils
{
    public static boolean isEmpty(String value)
    {
        // some code
    }

    public static String reverseString(String value)
    {
        // some code
    }
}

您真的想实例化到处都是的StringUtils对象,只是为了调用一个不存储任何成员变量的方法吗?在一个简单的程序中,这并不重要。但是一旦你的程序开始达到一定的规模,你调用这些方法数千次,那么我们就让实例化加起来吧。为什么?做一个纯粹主义者?这不值得花这么多钱。只需使用相同的实例

假设您有一个需要中央数据存储库的多线程应用程序。消费者和生产者使用或将数据放入存储库,包括通过接口访问存储库的外部应用程序对象

如果将此存储库设置为普通类对象,则会遇到初始化它并获取指向每个需要它的对象的指针的问题。这不是最难的问题,但它可能会与许多线程和对象混淆

另一方面,如果您这样做:

public enum Data implements MyInterface{
   INSTANCE;
       private final Whatevertype secretstuff = new Whatevertype();
       ...etc...
       public void PutThing( Sometype indata){ ... };
       public Sometype GetThing( int somecode ){ ...};
       ...etc...
 }
您(a)不必实例化任何内容,并且(b)可以使用

Data.INSTANCE.GetThing(42);

等等,就像高地人。。。只能有一个

,但传递指针以实现更易于阅读和维护的代码不是更好吗?事实上,这和全局变量的问题是一样的,但包装不同。当然,也可以从理论上看。但即使在那篇文章的示例中,您也将“CreditCard”类构造函数分解为6个成员,这只是一个简单的示例。让函数有10个以上的参数只是为了坚持意识形态不是一个好主意。通过构造函数传递所有依赖项只是进行依赖项注入的一种方法。另一种方法是设置属性。另一种选择是“服务定位器”模式。经典文章:服务定位器完全违背了它的目的,它基本上是一个单例包装器。仅供记录:在Python中,类对象是classobj(旧样式类)或type(新样式类)的实例。不,理想情况下,您希望这些方法能够像您建议的那样引入全局状态,从而使测试成为一场噩梦。