共享对象工厂的设计模式

时间:2018-01-03 15:02:25

标签: 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
// 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实例的一些机制)。我不喜欢这个解决方案的一些事情:

  1. 需要单身人士作为Widget实例获取租约的联系人
  2. 计时器用于管理地图:没有基于事件的方法来管理从我想到的地图中删除过期的租约。
  3. 继续#2:因为我正在使用计时器来管理地图中的租约到期,所以总会有一个小窗口,即使租约到期后租约仍保留在地图中,这意味着CreateLease()也有在返回之前检查weak_ptr是否已过期,如果找到现有的ID映射。
  4. 这种逻辑对我来说感觉不对。我需要额外关注这个想法,理想情况下建议更好的模式来解决这个问题。

1 个答案:

答案 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);
    }
}