美化的全局变量-变成一个美化的全局类。有人说打破面向对象设计。
给我一些场景,除了使用单例是有意义的良好的老记录器。
美化的全局变量-变成一个美化的全局类。有人说打破面向对象设计。
给我一些场景,除了使用单例是有意义的良好的老记录器。
当前回答
当你加载一个配置属性对象时,无论是从数据库还是从文件中,将它作为一个单例都会有所帮助;没有理由在服务器运行时重新读取不会改变的静态数据。
其他回答
首先,让我们区分一下单对象和单对象。后者是前者的许多可能实现之一。而且单对象的问题与单例的问题是不同的。单对象本身并不坏,有时是做事情的唯一方法。简而言之:
单对象-我只需要程序中对象的一个实例 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
将特定的基础设施关注点配置为单例或全局变量是非常实用的。我最喜欢的例子是依赖注入框架,它使用单例作为框架的连接点。
在这种情况下,您将依赖于基础设施来简化库的使用并避免不必要的复杂性。
使用单例的方法之一是覆盖一个实例,其中必须有一个“代理”控制对资源的访问。单例在日志记录器中很好,因为它们代理访问,比如说,一个文件,这个文件只能被写入。对于像日志这样的东西,它们提供了一种方法来抽象出对日志文件之类的东西的写操作——你可以将缓存机制包装到你的单例中,等等……
也可以考虑这样一种情况,你有一个应用程序,有许多窗口/线程等,但它需要一个单一的通信点。我曾经使用它来控制我希望应用程序启动的作业。单例程序负责将作业序列化,并将它们的状态显示给程序中其他感兴趣的部分。在这种情况下,你可以把单例对象看作是在应用程序中运行的“服务器”类……HTH
当你加载一个配置属性对象时,无论是从数据库还是从文件中,将它作为一个单例都会有所帮助;没有理由在服务器运行时重新读取不会改变的静态数据。
一个实例可以在Test::Builder中找到,这个类支持几乎所有现代Perl测试模块。Builder单例存储并代理测试流程的状态和历史记录(历史测试结果,计算运行的测试次数)以及测试输出流向等内容。这些都是协调由不同作者编写的多个测试模块以在单个测试脚本中一起工作所必需的。
The history of Test::Builder's singleton is educational. Calling new() always gives you the same object. First, all the data was stored as class variables with nothing in the object itself. This worked until I wanted to test Test::Builder with itself. Then I needed two Test::Builder objects, one setup as a dummy, to capture and test its behavior and output, and one to be the real test object. At that point Test::Builder was refactored into a real object. The singleton object was stored as class data, and new() would always return it. create() was added to make a fresh object and enable testing.
Currently, users are wanting to change some behaviors of Test::Builder in their own module, but leave others alone, while the test history remains in common across all testing modules. What's happening now is the monolithic Test::Builder object is being broken down into smaller pieces (history, output, format...) with a Test::Builder instance collecting them together. Now Test::Builder no longer has to be a singleton. Its components, like history, can be. This pushes the inflexible necessity of a singleton down a level. It gives more flexibility to the user to mix-and-match pieces. The smaller singleton objects can now just store data, with their containing objects deciding how to use it. It even allows a non-Test::Builder class to play along by using the Test::Builder history and output singletons.
似乎在数据的协调和行为的灵活性之间存在着一种推拉关系,这种关系可以通过在共享数据周围使用尽可能少的行为来缓解,以确保数据的完整性。