X

曜彤.手记

随记,关于互联网技术、产品与创业

吉 ICP 备10004938号

“对象性能类”设计模式(C++)


OOP 很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是对于某些情况,其所带来的成本必须被谨慎处理。

单例模式(Singleton)

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?这应该是类设计者的责任,而不是使用者的责任

模式定义:保证一个类仅有一个实例,并提供一个该实例的全局访问点。

非线程安全版实现

class Singleton {
  Singleton() = default;
  Singleton(const Singleton&) = delete;
 public:
  static Singleton* getInstance();
  static Singleton* instance;
};
Singleton* Singleton::instance = nullptr;
Singleton* Singleton::getInstance() {  // 线程非安全;
  if (instance == nullptr) {
    instance = new Singleton();
  }
  return instance;
}

线程安全,但锁代价过高版实现

class Singleton {
  Singleton() = default;
  Singleton(const Singleton&) = delete;
 public:
  static Singleton* getInstance();
  static Singleton* instance;
};
Singleton* Singleton::instance = nullptr;
std::mutex singletonMutex;
Singleton* Singleton::getInstance() {  // 线程安全,但锁代价太高;
  std::lock_guard<std::mutex> lock(singletonMutex);
  if (instance == nullptr) {
    instance = new Singleton();
  }
  return instance;
}

双检查锁,防止 CPU 乱序导致锁失效版实现

class Singleton {
  Singleton() = default;
  Singleton(const Singleton&) = delete;
 public:
  static Singleton* getInstance();
  static std::atomic<Singleton*> instance;
};
std::atomic<Singleton*> Singleton::instance = nullptr;
std::mutex singletonMutex;
Singleton* Singleton::getInstance() {  // 双检查锁;
  Singleton* _t = instance.load(std::memory_order_relaxed);
  std::atomic_thread_fence(std::memory_order_acquire);  // 下述代码对应机器指令将按顺序执行;
  if (_t == nullptr) {
    std::lock_guard<std::mutex> lock(singletonMutex);
    _t = instance.load(std::memory_order_relaxed);
    if (_t == nullptr) {
      _t = new Singleton(); 
      std::atomic_thread_fence(std::memory_order_release);
      instance.store(_t, std::memory_order_relaxed);  // 一次性赋值;
    }
  }
  return instance;
}

总结:

享元模式(Flyweight)

在软件系统中采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价 —— 主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?

模式定义:运用共享技术有效地支持大量细粒度的对象。

class Entity {
  std::string key;
 public:
  Entity(std::string key) : key(key) {}
};
class EntityPool {
  std::unordered_map<std::string, std::shared_ptr<Entity>> entityPool;  // 共享池;
 public:
  std::shared_ptr<Entity> getEntity(std::string key) {
    auto iter = entityPool.find(key);
    if (iter != entityPool.end()) {
      return entityPool[key];
    } else {
      auto _t = std::make_shared<Entity>(key);
      entityPool[key] = _t;
      return _t;
    }
  }
};
int main(int argc, char** argv) {
  EntityPool entityPool{};
  auto entity = entityPool.getEntity("Hello, world!");
  return 0;
}

总结:



这是文章底线,下面是评论
  暂无评论,欢迎勾搭 :)