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

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


当前回答

我认为单例的使用与数据库中的多对一关系是一样的。如果代码中有许多不同的部分需要处理对象的单个实例,那么使用单例就很有意义了。

其他回答

我认为如果你的应用程序有多个层次,如表示,领域和模型。Singleton是横切层的一个很好的候选者。并为系统各层提供服务。

从本质上讲,单例包装了一个服务,例如日志记录、分析,并将其提供给系统中的其他层。

是的,单例需要遵循单一责任原则。

因此,我正在为学校阅读单例模式,教授们策划了一份关于该主题的当前观点和最佳实践的列表。似乎有一个共识,即如果构建时不向代码中添加任何内容,则可以使用单例。如果您使单例使用可以被开启和关闭,并且除了工作负载之外没有其他副作用,那么使用这种设计模式是安全的,也是可取的。

当需要管理共享资源时,可以使用单例。例如打印机假脱机程序。您的应用程序应该只有一个假脱机程序实例,以避免对相同资源的请求冲突。

或者数据库连接或者文件管理器等等。

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

单对象-我只需要程序中对象的一个实例 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

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