我有一个系统,其中一个单例对象负责在其他非单例类之间创建和共享对象。例如:
// 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 所做的是创建一个新的租约,如果给定 ID 的映射中不存在的话。如果确实存在,则返回现有的共享对象。
我有一个计时器,它定期检查 m_leases
映射中是否存在“过期”的弱指针,如果是,将删除它们。这意味着在某个时候,多个小部件被销毁,随后也释放了它们的租约。
现在您已经了解了一些背景知识,我想我这里有一个比普通工厂更智能的工厂( Controller ):它会跟踪创建的实例,并且只根据特定的业务规则创建新的实例(具体来说,如果在 map 中找到匹配的 ID)。我不确定这是否是我正在尝试做的事情的最佳设计(即:一些在 Widget 的唯一实例之间共享 Lease 实例的机制)。这个解决方案有几点我不喜欢:
- 需要一个单例作为 Widget 实例获取 Lease 的联系点
- 计时器用于管理 map :我没有想到基于事件的方法来管理从 map 中删除过期租约。
- 继续 #2:因为我使用定时器来管理 map 中的租约到期,所以总是有一个小窗口,租约即使在到期后仍保留在 map 中,这意味着
CreateLease()
还必须检查weak_ptr
是否过期,如果找到现有的 ID 映射,则返回它。
我觉得这个逻辑不对。我需要更多的关注这个想法,最好是推荐更好的模式来解决这个问题。
最佳答案
我会在析构函数中广播租约 - 观察者模式。
这将允许 Controller 注册一个观察者以删除租约并将其删除。这消除了您对计时器的需要,并引入了事件的概念;满足 2 和 3。
至于 Controller 是单例的,从你发布的内容来看,它可以嵌套到Widget中并设为私有(private)(或移动到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);
}
}
关于c++ - 共享对象工厂的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48079956/