美化的全局变量-变成一个美化的全局类。有人说打破面向对象设计。

给我一些场景,除了使用单例是有意义的良好的老记录器。


当前回答

您可以在实现状态模式时使用单例(以GoF书中所示的方式)。这是因为具体的State类没有自己的状态,而是根据上下文类执行它们的操作。

你也可以让抽象工厂成为一个单例。

其他回答

首先,让我们区分一下单对象和单对象。后者是前者的许多可能实现之一。而且单对象的问题与单例的问题是不同的。单对象本身并不坏,有时是做事情的唯一方法。简而言之:

单对象-我只需要程序中对象的一个实例 Singleton -创建一个带有静态字段的类。添加一个返回此字段的静态方法。在第一次调用时惰性地实例化一个字段。总是返回相同的对象。

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton instance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

如您所见,规范形式的“单例”模式对测试不是很友好。不过,这个问题很容易解决:只要让Singleton实现一个接口。让我们称它为“可测试单例”:)

public class Singleton implements ISingleton {
    private static Singleton instance;

    private Singleton() {}

    public static ISingleton instance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

现在我们可以模拟Singleton了,因为我们通过接口来使用它。其中一项索赔消失了。让我们看看是否可以去掉另一个声明-共享全局状态。

如果我们剥离单例模式,它的核心是惰性初始化:

public static ISingleton instance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

这就是它存在的全部原因。这就是单对象模式。我们把它拿走,放到工厂方法中,例如:

public class SingletonFactory {
    private static ISingleton instance;

    // Knock-knock. Single Object here
    public static ISingleton simpleSingleton() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

与我们的可测试单例有什么不同?没有,因为这是单对象模式的本质——不管你是把它实现为单例、工厂方法还是服务定位器。你仍然有一些共享的全局状态。如果从多个线程访问它,这可能会成为一个问题。您将不得不使simpleSingleton()同步并处理所有多线程问题。

再说一遍:无论你选择什么方法,你都必须付出单一对象的代价。使用依赖注入容器只是将复杂性转移到框架,它将不得不处理单对象的固有问题。

回顾:

Most of people who mention Singleton mean Single Object One of the popular ways to implement it is the Singleton pattern It has its flaws that can be mitigated However, the most of Singleton's complexity roots in Single Object's complexity Regardless of how you instantiate your Single Object, it's still there, be it a Service Locator, a Factory Method or something else You can shift the complexity to a DI container which is (hopefully) well-tested Sometimes using the DI container is cumbersome - imagine injecting a LOGGER to every class

共享资源。特别是在PHP中,数据库类、模板类和全局变量库类。所有这些都必须由代码中使用的所有模块/类共享。

这是一个真正的对象使用——>模板类包含正在构建的页面模板,它被添加到页面输出的模块塑造、添加、更改。它必须保持为单个实例,这样才能实现这一点,数据库也是如此。使用共享数据库单例,所有模块的类都可以访问查询,并且无需重新运行查询。

全局变量仓库单例为您提供了一个全局的、可靠的、易于使用的变量仓库。它极大地整理了你的代码。想象一下,所有配置值都在一个单例数组中,如下所示:

美元gb - > problem[’hostname’]

或者将所有的语言值放在一个数组中,比如:

gb - >朗(“ENTER_USER”)

在运行页面代码的最后,你会得到,比如说,一个现在成熟的:

美元的模板

Singleton,一个$gb的Singleton,其中有lang数组用于替换,所有输出都已加载并准备就绪。您只需将它们替换为现在在成熟模板对象的页面值中呈现的键,然后将其提供给用户。

这样做的最大好处是你可以对任何东西做任何你喜欢的后期处理。您可以将所有语言值输送到谷歌translate或其他翻译服务,并将它们返回,并将它们替换到它们的位置,例如,已翻译。或者,您可以根据需要替换页面结构或内容字符串。

我不认为Singleton的场景与记录器、打印机池或任何示例相关。

单例决策的目的是优化硬件资源,而不是只有一个地方来控制任何记录器或打印机池

我个人认为单例应该在以下情况下使用:

我们正在谈论的对象总是以相同的方式实例化(即任何共享资源,如Logger或打印机池) 它被多次调用(这可以是100或1000,这与您的资源有关) 你的硬件资源是有限的(例如内存、处理能力等)。

如果你有大量的内存空间和处理能力,我认为没有必要使用单例。

Singleton将确保你只有一个实例,并且是惰性加载的,那么如果它被调用一百万次,你就只创建了一个对象。

当你加载一个配置属性对象时,无论是从数据库还是从文件中,将它作为一个单例都会有所帮助;没有理由在服务器运行时重新读取不会改变的静态数据。

管理到数据库的连接(或连接池)。

我还会使用它来检索和存储外部配置文件中的信息。