帮我删除辛格尔顿:寻找替代

背景:我有一些类实现,我已经线程安全的对象/观察者设计模式。 一个subject将通知它的observers通过简单的方法调用observer->Notified( this )如果observer建于同一个线程中正在取得的通知。 但是,如果observer是在不同的线程构建的,则该通知将被张贴到queue要由该构造的螺纹购买处理observer然后当通知事件被处理简单方法调用可以进行。

所以...我有一个地图关联的线程和队列,当线程和队列构造和销毁得到更新。 这张地图本身使用一个互斥体保护的多线程访问它。

该地图是一个单例。

我一直在内疚使用单身,在过去,因为“会有只有一个在此应用程序”,并相信我 - 我已经付出了我的忏悔!

我的一部分不禁想到,真的有将只有一个队列/在一个应用程序线程的地图。 另一个声音说,单身并不好,你应该避免。

我喜欢拆卸单,并能够存根它为我的单元测试的想法。 麻烦的是,我有一个很难试图想出一个很好的替代方案。

这在过去曾在“一切如常”的解决方案是一个指针传递给该对象使用引用单代替。 我认为这将是棘手的在这种情况下,由于观察员和对象是10-A-一分钱在我的应用程序,它会很别扭必须通过队列/线程映射对象到每一个观察者的构造函数。

我感激的是,我可能只有一个在我的应用程序映射,但它不应该是在主体和观察者类代码中作出这一决定的肠子。

也许这是一个有效的单,但我也很欣赏我怎么可以删除它的任何想法。

谢谢。

PS。 我已阅读http://stackoverflow.com/questions/1300655/whats-alternative-to-singleton在这篇文章中公认的答案提及。 我不禁想起了ApplicationFactory它只是另一个单身的另一个名字。 我实在看不出优势。

--------------解决方案-------------

如果唯一的目的,以试图摆脱单身是从单元测试的角度来看,也许更换单吸的东西,你可以在一个存根交换。

class QueueThreadMapBase
{
//virtual functions
};

class QeueueThreadMap : public QueueThreadMapBase
{
//your real implementation
};

class QeueueThreadMapTestStub : public QueueThreadMapBase
{
//your test implementation
};

static QueueThreadMapBase* pGlobalInstance = new QeueueThreadMap;

QueueThreadMapBase* getInstance()
{
return pGlobalInstance;
}

void setInstance(QueueThreadMapBase* pNew)
{
pGlobalInstance = pNew
}

那么在您的测试只是换出队列/线程映射实现。 至少,这暴露了单多一点。

一些思想对一个解决方案:

为什么你需要排队通知在不同的线程创建的观察员? 我最好的设计是有subject刚直接通知的观察员,并把责任上的观察者来实现自己的线程安全的,与知识Notified()可以被调用从另一个线程的任何时间。 观察者知道哪些需要它们的状态的部分与锁被保护,并且它们可以处理比更好subjectqueue

假设你真的有一个很好的理由保持queue ,为什么不把它的一个实例? 只是不要queue = new Queue()介于main ,然后通过周围的参考。 可能只有每一个是一个,但你仍然可以把它看成一个实例,而不是一个全局静态。

什么是错把队列中的主题类里面? 你需要什么地图呢?

你已经有一个线程从单队列地图阅读。 :相反,这样做只是让拍摄对象类中的地图,并提供了两种订阅观察员

class Subject
{
// Assume is threadsafe and all
private QueueMap queue;
void Subscribe(NotifyCallback, ThreadId)
{
// If it was created from another thread add to the map
if (ThreadId != This.ThreadId)
queue[ThreadId].Add(NotifyCallback);
}

public NotifyCallBack GetNext()
{
return queue[CallerThread.Id].Pop;
}
}

现在,任何线程可以调用的GetNext方法来启动调度...当然它是所有过于简单,但它只是想法。

注:我正在与你已经有解决这个模式的架构,这样你已经有一堆观察员,一个或多个科目,而且线程已经进入地图做通知的前提。 这摆脱了单身,但我建议你在同一个线程通知,让观察者处理并发问题。

我的做法是让观察者提供了一个队列,当他们与主体登记; 观察者的所有者将负责两个线程和相关的队列,并且对象将在观察者与队列相关联,而无需中央登记。

线程安全观察员可以不注册一个队列,由主体直接调用。

您的观察家可能会便宜,但他们赖以生存的通知队列线程地图上,对不对?

什么是尴尬的有关使这种依赖性明确,并采取控制它?

至于申请工厂MISKO Hevery描述了在他的文章,最大的优点是:1)工厂的做法并不能掩盖的依赖; 2)你所依赖的单一实例不是全局可用,这样其他对象可以染指的州。 因此,使用这种方法,在任何给定的顶级应用程序上下文,你确切地知道什么是使用地图。 随着全球访问单身,你使用任何类可能会做或到地图令人厌恶的事情。

怎么样将一个返回一个单独到其初始状态,你可以测试之间调用Reset方法? 这可能是比存根简单。 这也许可以通用的复位方法添加到一个Singleton模板(删除内部单平普尔和重置指针)。 这甚至可能包括与主ResetAll方法中的所有单身的注册表,以重置所有的人!

分类:C# 时间:2015-03-14 人气:0
本文关键词: C#,设计模式,单
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.715 (s). 10 q(s)