C++ 共享对象工厂的设计模式
我有一个系统,其中一个单例对象负责在其他非单例类之间创建和共享对象。例如:C++ 共享对象工厂的设计模式,c++,design-patterns,C++,Design Patterns,我有一个系统,其中一个单例对象负责在其他非单例类之间创建和共享对象。例如: // One instance is shared between multiple instances // of Widget that have the same ID. class Lease {}; // For each unique Widget instance that has the same // value for `m_id`, the Controller will either // cr
// One instance is shared between multiple instances
// of Widget that have the same ID.
class Lease {};
// For each unique Widget instance that has the same
// value for `m_id`, the Controller will either
// create a new Lease (if one has not already been
// created) or it will return an existing one.
class Widget
{
private:
unsigned m_id{};
std::shared_ptr<Lease> m_lease;
};
// Singleton object that is used by all instances of
// Widget to obtain shared instances to Lease
class Controller
{
public:
std::shared_ptr<Lease> CreateLease(unsigned id);
private:
std::map<unsigned, std::weak_ptr<Lease>> m_leases;
};
//一个实例在多个实例之间共享
//具有相同ID的小部件的。
类租约{};
//对于具有相同
//值,则控制器将
//创建新租约(如果尚未创建)
//或者它将返回一个现有的。
类小部件
{
私人:
无符号m_id{};
std::共享ptr m_租约;
};
//的所有实例所使用的单例对象
//获取要租赁的共享实例的小部件
类控制器
{
公众:
std::shared_ptr CreateLease(未签名的id);
私人:
标准::地图m_租赁;
};
这就是我目前的要点。控制器所做的是,如果给定ID的映射中不存在新租约,则创建新租约。如果确实存在,则返回现有的共享对象
我有一个计时器,可以定期检查m\u租约
映射中的“过期”弱指针,如果是,将删除它们。这意味着,在某个时候,多个小部件被销毁,随后也释放了它们的租约
既然您有了一些背景知识,我想我这里有一个比普通工厂更聪明的工厂(控制器):它跟踪实例的创建,并且只根据某些业务规则创建新的实例(特别是,如果在映射中找到匹配的ID)。我不确定这是否是我尝试做的最好的设计(也就是说:在Widget的唯一实例之间共享租约实例的某种机制)。此解决方案有几点我不喜欢:
CreateLease()
在返回之前,还必须检查弱ptr
是否过期,如果找到了现有的ID映射我觉得这个逻辑不对。我需要更多的眼光来看待这个想法,最好是推荐更好的模式来解决这个问题。我会在析构函数中广播租约-观察者模式 这将允许控制者注册一名观察员,以便删除租约并将其删除。这消除了对计时器的需求,引入了事件的概念;满足2和3 至于控制器是一个单体,根据您发布的内容,它可以嵌套到小部件中并成为私有的(或者移动到小部件的cpp文件中)。虽然它最终仍然是一个单例,但由于它的范围有限,它的控制性更强,可以很容易地在以后被替换 如何将其组合在一起的示例:
class Lease {
public:
struct listener {
virtual void leaseGone(int id) = 0;
}
void addListener(listener* l) {
listeners.push_back(l);
}
~Lease() {
for (auto x&: listeners)
x->leaseGone(myId);
}
}
class Controller : Lease::listener {
void leaseGone(int id) {
m_leases.erase(id);
}
}
我喜欢这个想法,但可能有未指定的行为:我的编辑显示了它如何不会击中这个UB,因为它根本不测试弱点有效性-它知道它无效;所以不需要测试我刚才看到了你的例子。链接SO仅因为我的租约地图使用弱ptr才相关。在
租约
的析构函数中,在检查弱ptr::expired()
之前,共享ptr的使用计数()
必须为0,这是我计划在removeLeaseFromMap()
实现内部执行的额外检查。但是仔细想想,这可能是不必要的,因为调用了Lease析构函数这一事实意味着ref count为0,否则它不会被析构函数。确切地说,removeLeaseFromMap()不需要做任何检查,因为它已经消失了。完美。回答得很好。感谢您提供的示例代码。为了总结讨论,我建议您更新代码示例,以显示removeLeaseFromMap
的实现,以显示仅m_租赁。擦除(id)需要调用code>,并且不检查弱\u ptr::expired()
。这是为了你的答案的未来观众的利益。再次感谢!!“我有一个计时器,可以定期检查m_租约映射中的“过期”弱指针,如果是,将删除它们。这意味着在某个时刻,多个小部件被销毁”:当您在映射中存储弱_ptr
时,您的映射清理(删除null ptr
弱_ptr
)不会释放小部件。这只是对映射的优化。