我有一个系统,其中单例对象负责在其他非单例类之间创建和共享对象。例如:
// 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;
};
这是我目前所拥有的要点。 Controller的作用是创建一个新的Lease,如果给定ID的映射中尚不存在。如果它确实存在,则返回现有的共享对象。
我有一个计时器,定期检查m_leases
地图中的“已过期”弱指针,如果是这样,我们会删除它们。这意味着在某些时候,多个小部件被销毁,随后也释放了他们的租约。
既然你有一些背景知识,我认为我在这里的工厂(控制器)比普通工厂更聪明:它跟踪实例是创建的,只根据某些业务规则创建新实例(具体而言,如果在地图中找到匹配的ID)。我不确定这是否是我正在尝试做的最好的设计(那就是:在Widget的独特实例之间共享Lease实例的一些机制)。我不喜欢这个解决方案的一些事情:
CreateLease()
也有在返回之前检查weak_ptr
是否已过期,如果找到现有的ID映射。这种逻辑对我来说感觉不对。我需要额外关注这个想法,理想情况下建议更好的模式来解决这个问题。
答案 0 :(得分:1)
我会在析构函数中播放租约 - 观察者模式。
这将允许Controller注册观察员以删除租约并将其删除。这消除了您对计时器的需求,并介绍了事件的概念;满足2&amp; 3。
对于作为单身的控制器,根据您发布的内容,它可以嵌套到Widget中并使其成为私有(或移动到Widget的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);
}
}