我有一个实现Singleton设计模式的对象缓存.我对单例的方法总是在首次访问属性时延迟加载静态实例.
public static Widget
{
get
{
if(instance==null) instance = new Widget();
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我知道这种方法不是线程安全的,并且实例检查为null会导致效率低下.在实例化静态实例的类上实现静态构造函数是否明智?
据我所知,只要第一次静态属性访问发生,就会调用静态构造函数.这是否有效,它是否会提供超过当前延迟加载方法的任何好处,或者更好地探索代理实现,还是使用锁来强制它是线程安全的?
public static Widget
{
get
{
if(instance==null)
{
lock(padlock)
{
if(instance==null) instance = new Widget();
}
}
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我没有很多静态构造函数的经验,所以如果它是延迟加载属性的相同或更差的实现,不要想要实现这个想法.
干杯,加里
今天我在面试中遇到了一个问题.是否可以在Singleton类上应用继承概念?我说因为构造函数是私有的,所以我们不能扩展那个Singleton类.
他问我的下一件事是在Singleton类上应用继承.因此,我将Singleton的构造函数视为受保护的思想,即child的构造函数也受到保护.但我错了,孩子可以有一个等于或高于此的修饰符.
所以,我让他给出一个关于这种情况的真实世界的例子.他无法给我一个,并说我无法提出问题,并希望我告诉他们这种情况是否可能.
我有点空白.我的问题是,
我已经看过在Scala中登录的示例,它通常看起来像这样:
import org.slf4j.LoggerFactory
trait Loggable {
private lazy val logger = LoggerFactory.getLogger(getClass)
protected def debug(msg: => AnyRef, t: => Throwable = null): Unit =
{...}
}
Run Code Online (Sandbox Code Playgroud)
这似乎与具体的日志框架无关.虽然这样做了,但它还在每个想要进行日志记录的实例中引入了一个无关的lazy val ,这可能是整个应用程序的每个实例.这对我来说似乎太沉重了,特别是如果你有一些特定类型的"小实例".
有没有办法将记录器放在具体类的对象中,只需使用继承?如果我必须在类的对象中显式声明记录器,并从类/特性显式地引用它,那么我编写的代码几乎和我根本没有重用的代码一样多.
在非日志记录特定上下文中表示,问题是:
如何在特征中声明实现类必须具有X类型的单例对象,并且必须通过方法def x:X访问此单例对象?
我不能简单地定义一个抽象方法,因为在类中只能有一个实现.我希望在超级类中登录让我获得超类单例,并且登录子类会让我获得子类单例.或者更简单地说,我希望登录Scala能像Java中的传统日志一样工作,使用特定于执行日志记录的类的静态记录器.我目前对Scala的了解告诉我,如果不像在Java中那样完全相同,这是不可能的,没有太多使用"更好"的Scala带来的好处.
好吧,这是现实世界的场景:我正在编写一个应用程序,我有一个代表某种类型文件的类(在我的例子中,这是照片,但细节与问题无关).Photos类的每个实例对于照片的文件名应该是唯一的.
问题是,当用户告诉我的应用程序加载文件时,我需要能够识别文件何时已加载,并使用现有实例作为该文件名,而不是在同一文件名上创建重复实例.
对我而言,使用memoization似乎是一个很好的情况,并且有很多例子,但在这种情况下,我不只是记住一个普通的函数,我需要记忆__init__().这造成了一个问题,因为在__init__()被调用的时候已经太晚了,因为已经创建了一个新实例.
在我的研究中,我发现了Python的__new__()方法,我实际上能够编写一个简单的工作示例,但是当我尝试在我的真实世界对象上使用它时它就崩溃了,我不知道为什么(我唯一可以做到的)我想到的是我的真实世界对象是我无法控制的其他对象的子类,因此这种方法存在一些不兼容性.这就是我所拥有的:
class Flub(object):
instances = {}
def __new__(cls, flubid):
try:
self = Flub.instances[flubid]
except KeyError:
self = Flub.instances[flubid] = super(Flub, cls).__new__(cls)
print 'making a new one!'
self.flubid = flubid
print id(self)
return self
@staticmethod
def destroy_all():
for flub in Flub.instances.values():
print 'killing', flub
a = Flub('foo')
b = Flub('foo')
c = Flub('bar')
print a
print b
print c
print a is b, b is c
Flub.destroy_all()
Run Code Online (Sandbox Code Playgroud)
哪个输出:
making a new one! …Run Code Online (Sandbox Code Playgroud) 我目前正在测试Firebase以及我打算在整个应用程序的生命周期中使用的Singleton模型.我现在已经陷入了一些似乎非常微不足道的事情,但我无法理解我的生活.我有一个我使用的模型示例:firebase中的书签.
public class BookSingleton {
private static BookSingleton model;
private ArrayList<BookMark> bookmarks = new ArrayList<BookMark>();
public static BookSingleton getModel()
{
if (model == null)
{
throw new IllegalStateException("The model has not been initialised yet.");
}
return model;
}
public ArrayList<Bookmark> theBookmarkList()
{
return this.bookmarks;
}
public void setBookmarks(ArrayList<Bookmark> bookmarks){
this.bookmarks = bookmarks;
}
public void loadModelWithDataFromFirebase(){
Firebase db = new Firebase(//url);
Firebase bookmarksRef = fb.child(//access correct child);
final ArrayList<Bookmark> loadedBookmarks = new ArrayList<Bookmark>();
bookmarksRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot …Run Code Online (Sandbox Code Playgroud) 当我第一次看到反单身评论时,我很困惑.我在最近的一些项目中使用了单例模式,并且它运行得很漂亮.事实上,我已经使用了很多次.
现在,在遇到一些问题之后,阅读这个问题,尤其是这篇博文,我理解了我带给世界的邪恶.
那么:我如何从现有代码中删除单例?
例如:
在零售店管理程序中,我使用了MVC模式.我的Model对象描述了商店,用户界面是View,我有一组控制器,它们充当两者之间的联络.大.除了我将Store变成一个单独的(因为应用程序一次只管理一个商店),我还把我的大部分Controller类变成了单例(一个mainWindow,一个menuBar,一个productEditor ......).现在,我的大多数Controller类都可以像这样访问其他单例:
Store managedStore = Store::getInstance();
managedStore.doSomething();
managedStore.doSomethingElse();
//etc.
Run Code Online (Sandbox Code Playgroud)
我应该改为:
Globals仍然很糟糕,但至少他们不会假装.
我看到#1迅速导致可怕的膨胀构造函数调用:
someVar = SomeControllerClass(managedStore, menuBar, editor, sasquatch, ...)
Run Code Online (Sandbox Code Playgroud)
还有其他人经历过这个吗?如果不是全局变量或单个变量,那么为多个单独的类访问公共变量的OO方法是什么?
目前我对这种"设计模式"非常感兴趣.我不确定是否有使用这种严格的全局状态实施的垮台.那么,你认为什么时候不在应用程序中练习单身?
有没有人知道是否可以像没有记录器一样的类:
使用单例或全局(la std :: cout)
将实例/指针/引用传递给需要它的每个方法
我以一个记录器类为例,但我的应用程序中有一些类可以从中受益(例如,撤消管理器).
每个解决方案都有几个问题:
使用单例对于测试来说是有问题的(还有许多原因,使用单例通常不是一个好主意).全球化也是如此.此外,没有什么可以保证应用程序中只有一个实例,甚至不是一个要求(例如,为什么没有2个记录器?)
将它传递给每个对象构造函数(依赖注入),导致很多样板代码,并且可能容易出错,因为你必须多次复制/粘贴相同的代码.可以认真考虑在每个类的构造函数中都有一个指向Logger的指针???????
所以我想知道是否有第三种选择,在C++中,我从未听说过?对我而言,听起来它需要一些黑魔法引擎盖,但我对我在堆栈溢出中学到的一些技术感到惊喜,这是我在google中找不到的,所以我知道这里有一些真正的大师;)
令人惊讶的是,我发现了许多关于如何设计单身人士的讨论,或者为什么不应该使用单身人士,但我找不到一个解决我的问题的帖子......
如何在Ruby中重置单个对象?我知道在真正的代码中我们永远不想这样做但是单元测试呢?
这是我在RSpec测试中尝试做的事情 -
describe MySingleton, "#not_initialised" do
it "raises an exception" do
expect {MySingleton.get_something}.to raise_error(RuntimeError)
end
end
Run Code Online (Sandbox Code Playgroud)
它失败是因为我之前的一个测试初始化了单例对象.我试过从这个链接开始关注Ian White的建议,它基本上是猴子补丁Singleton来提供reset_instance方法,但我得到一个未定义的方法'reset_instance'异常.
require 'singleton'
class <<Singleton
def included_with_reset(klass)
included_without_reset(klass)
class <<klass
def reset_instance
Singleton.send :__init__, self
self
end
end
end
alias_method :included_without_reset, :included
alias_method :included, :included_with_reset
end
describe MySingleton, "#not_initialised" do
it "raises an exception" do
MySingleton.reset_instance
expect {MySingleton.get_something}.to raise_error(RuntimeError)
end
end
Run Code Online (Sandbox Code Playgroud)
在Ruby中最常用的方法是什么?
我正在制作一个对象,用于下载所有视图控制器的内容.该对象是单例实例,并且在下载完成后具有带有接收数据的回调方法.它还有一个委托属性,以便在下载完成后知道要回调哪个对象.
有多个控制器使用此共享实例,我的问题是如何回调请求下载的正确视图控制器.
我的方法是使用委托,但问题是,由于其他视图控制器也是它的委托,下载对象可以回调每个对象,这将很难跟踪.