我只需要在某处阅读以下代码:
public class SingletonObjectDemo {
private static SingletonObjectDemo singletonObject;
// Note that the constructor is private
private SingletonObjectDemo() {
// Optional Code
}
public static SingletonObjectDemo getSingletonObject() {
if (singletonObject == null) {
singletonObject = new SingletonObjectDemo();
}
return singletonObject;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要知道这部分需要什么:
if (singletonObject == null) {
singletonObject = new SingletonObjectDemo();
}
Run Code Online (Sandbox Code Playgroud)
如果我们不使用这部分代码怎么办?仍然会有一个副本SingletonObjectDemo,为什么我们需要这个代码呢?
我有 ac# 网络服务。当我收到新请求时,我创建一个日志记录实例。我有许多其他类的实例来处理请求,我希望它们也记录下来。共享日志记录实例而不将其传递到构造函数或属性中的最佳方法是什么?
我正在阅读单身模式的缺点.在许多论坛中建议的有效使用单例是Logging应用程序.我想知道为什么这是模式的有效使用.我们不是在整个应用程序中维护内存中的状态信息吗?
为什么不使用一个函数:
class Logger
{
public static void Log(string message)
{
//Append to file
}
}
Run Code Online (Sandbox Code Playgroud) 我正在开发计算机视觉应用程序,我将需要Classifier类.这个类在每次运行时都是不可变的,它在初始化时从磁盘加载训练过的数据.我想确保整个程序可以访问相同的训练数据,并且我希望在加载后阻止从磁盘重新加载.
我考虑的是使用静态类或单例.我不确定如何将数据加载到静态类,因为在编译时不知道数据文件的路径 - 它将是程序参数.所以我在考虑Singleton模式,但我不知道如何动态初始化它.
我的想法是使用以下:
class Singleton {
private static Singleton instance;
private Singleton() { ... }
private static SomeDataObject data;
public static Singleton getInstance() {
if(instance == null)
instance = new Singleton();
return instance;
}
public static init(string dataPath){
if(data == null)
loadDataFromFile(dataPath)
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为我无法控制首先调用哪个方法.
我知道正确的方法是在开始时用数据创建实例并将其传递给需要它的所有类和方法,但这不是真正的通用解决方案.我可以在我自己的代码中跟踪对Classifier的所有调用,但是如果我将代码作为API,这将是一个问题.
简而言之,如何在运行时初始化单例?
我有共同的代码(我称之为控制器的多个类)需要由项目中的多个包共享.我正在考虑创建一个返回这些控制器的工厂.因此,工厂将有一个hashmap,可以返回请求的控制器,如果没有创建,则创建一个新的.控制器有公共代码,因为我不需要创建这些控制器的多个实例,我认为它们应该是单例.
这看起来像是一个好方法吗?
我有这个:
单例.h
#ifndef SINGLETON_H
#define SINGLETON_H
#include <atomic>
#include <mutex>
class Singleton
{
public:
static std::atomic<Singleton*> Singleton::m_instance;
static std::mutex Singleton::m_mutex;
static Singleton* getInstance();
Singleton();
~Singleton();
};
#endif
Run Code Online (Sandbox Code Playgroud)
单例.cpp
#include "Singleton.h"
Singleton::Singleton()
{
}
Singleton* Singleton::getInstance()
{
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr)
{
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr)
{
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
Singleton::~Singleton() {}
Run Code Online (Sandbox Code Playgroud)
主程序
#include "Singleton.h"
#include <iostream>
int main()
{
Singleton* singleton …Run Code Online (Sandbox Code Playgroud) 我正在使用弹性搜索传输客户端连接到弹性搜索.我尝试过两种方法
1)在我的整个应用程序中共享Singleton客户端.响应时间在1-2秒之间
2)每次调用Elastic Search的新客户端实例,大约需要7秒才能响应.具体而言,有5个类需要连接ES群集,此方法为每个类创建一个新的传输客户端.
1)在弹性搜索方面是一个很好的方法,因为通常不建议使用单例数据库连接对象吗?
是否有可用于Elastic Search的连接池机制,就像我们有关系数据库的DBCP一样?
我讨厌打败一匹死马,也就是说,在过去的几天里,我已经阅读了很多关于使用单例模式的相互矛盾的文章。
这个问题不是一般来说哪个是更好的选择,而是什么对我的用例有意义。
我正在做的宠物项目是一个游戏。我目前正在处理的一些代码,我倾向于使用单例模式。
用例如下:
现在澄清一下,以上几个要求在访问之间共享状态。例如,记录器正在包装一个日志库并需要一个指向输出日志的指针,网络需要一个已建立的开放连接等。
现在,据我所知,更建议避免单身人士,所以让我们看看我们如何做到这一点。很多文章只是说在顶部创建实例并将其作为参数传递到需要的任何地方。虽然我同意这在技术上是可行的,但我的问题就变成了,如何管理潜在的大量参数?好吧,我想到的是将不同的实例包装在一种“上下文”对象中并传递它,然后执行类似context->log("Hello World"). 现在确定这还不错,但是如果您有这样的框架怎么办:
game_loop(ctx)
->update_entities(ctx)
->on_preupdate(ctx)
->run_something(ctx)
->only use ctx->log() in some freak edge case in this function.
->on_update(ctx)
->whatever(ctx)
->ctx->networksend(stuff)
->update_physics(ctx)
->ctx->networksend(stuff)
//maybe ctx never uses log here.
Run Code Online (Sandbox Code Playgroud)
你明白了......在某些领域,“ctx”的某些方面从未使用过,但你仍然坚持在任何地方传递它,以防你可能想使用记录器调试某些东西,或者稍后在开发中,您实际上需要网络或该部分代码中的任何内容。
我觉得上面的例子更适合全局可访问的单例,但我必须承认,我来自 C#/Java/JS 背景,这可能会影响我的观点。我想采用 C++ 程序员的心态/最佳实践,但就像我说的那样,我似乎找不到直接的答案。我还注意到,那些建议只将“单例”作为参数传递的文章只给出了非常简单的用例,任何人都会同意参数是更好的方法。
在这个游戏示例中,即使您不打算立即使用它,您也可能不想在任何地方访问日志记录。文件系统的东西可能已经结束了,但在你构建项目之前,很难说它何时/何地最有用。
我也是:
如果选项 1,从性能的角度来看,我应该切换到使用命名空间函数,并将“私有”变量/函数隐藏在匿名命名空间中,就像大多数人在 C 中所做的那样?(我猜性能会有小幅提升,但随后我将不得不在其中一些方法上调用“init”和“destroy”方法,而不能只允许构造函数/析构函数为我做这件事,仍然值得吗?)
现在我意识到这可能有点基于意见,但我希望当遇到更复杂/嵌套的代码库时,我仍然可以得到一个相对较好的答案。
编辑: 经过深思熟虑,我决定改用“服务定位器”模式。为了防止服务定位器的全局/单例,我正在制作任何可能使用从抽象基类继承的服务的东西,该抽象基类要求在构造时传递服务定位器。
我还没有实现所有的东西,所以我仍然不确定我是否会遇到这种方法的任何问题,并且仍然会喜欢关于这是否是单例/全局范围困境的合理替代方案的反馈。
我读过 Service Locator 也有点反模式,也就是说,我发现的许多示例都是用静态和/或作为单例实现的,也许像我所描述的那样使用它会删除导致它是一个反模式?
对于 REST api,它在请求之间没有依赖关系并且使用 ASP.NET Core DI。
在选择最合适的方式时,我听到了相互矛盾的论点:
我知道它们的工作方式不同,但是有“首选”的生命周期吗?它是否应该从“瞬态”开始并根据需要转移到其他人身上?
是否有任何调查证明单例节省的实例化时间实际上是相关的?