【现代C++】 线程安全的工厂模式

111 阅读1分钟

来自于《Linux多线程服务端编程:使用 muduo C++网络库》/陈硕。

该工厂模式与对象池弱引用管理机制结合,使用弱引用表间接管理已创建对象,避免重复创建相同 key 的实例。同时,利用析构回调函数维护对象生命周期,保证了线程安全的对象回调与析构。

封装Product对象创建逻辑:

Factoryget()方法根据传入的key创建或返回Product对象,封装对象的创建过程。使用时仅仅需指定key,无需关心Product的具体实例化细节。

延迟实例化与解耦:

通过weak_ptr管理Product对象,仅在首次请求时创建实例(通过new Product(key)),后续请求复用现有对象,同时避免了shared_ptr循环引用导致的内存泄漏。在对象析构时通过weakDeleteCallback自动清理products_中的记录,来维护对象缓存。

本工厂模式与对象池区别在于:对象池主动管理可复用对象的存活,而该工厂模式仅被动跟踪对象生命周期。

class Factory : public boost::enable_shared_from_this<Factory>,
                     boost::noncopyable
{
 public:
  boost::shared_ptr<Product> get(const string& key)
  {
    boost::shared_ptr<Product> spProduct;
    muduo::MutexLockGuard lock(mutex_);
    boost::weak_ptr<Product>& wpProduct = Products_[key];
    spProduct = wpProduct.lock(); // try to control spProduct
    if (!spProduct)
    {
      // if failed, means spProduct doesn't exist
      // new one and bind delete callback 
      spProduct.reset(new Product(key),
                   boost::bind(&Factory::weakDeleteCallback,
                               boost::weak_ptr<Factory>(shared_from_this()),
                               _1));
      wpProduct = spProduct;
    }
    return spProduct;
  }

 private:
  static void weakDeleteCallback(const boost::weak_ptr<Factory>& wpFactory,
                                 Product* Product)
  {
    printf("weakDeleteProduct[%p]\n", Product);
    boost::shared_ptr<Factory> factory(wpFactory.lock());
    if (factory) {
      factory->removeProduct(Product);
    }else {
      printf("factory died.\n");
    }
    delete Product;  // sorry, I lied
  }

  void removeProduct(Product* Product)
  {
    if (Product)
    {
      muduo::MutexLockGuard lock(mutex_);
      auto it = Products_.find(Product->key());
      if (it != Products_.end() && it->second.expired())
      {
        Products_.erase(Product->key());
      }
    }
  }

 private:
  mutable muduo::MutexLock mutex_;
  std::map<string, boost::weak_ptr<Product> > Products_;
};