DesignPattern-part1
阅读原文时间:2023年09月06日阅读:1
title: "modern C++ DesignPattern-Part1"
date: 2018-04-03T16:06:33+08:00
lastmod: 2018-04-03T16:06:33+08:00
draft: false
keywords: [设计模式]
tags: [设计模式, C++]
categories: []

现代c++改变了很多设计模式的实现方式,为了保持与时俱进,阅读了"Design Pattern in Modern C++"这本书,会记录下来在阅读中的一些心得体会,Part1主要包括 工厂模式,建造者模式与单例模式的现代实现


Abstract Factory

struct HotDrinkFactory {
  virtual unique_ptr<HotDrink> make() const = 0;  };
};
struct CoffeeFactory : HotDrinkFactory{
 unique_ptr<HotDrink> make() const override {
 return make_unique<Coffee>();
}};

class DrinkFactory {
  map<string, unique_str<HotDrinkFactory>> hot_factories;
public:
  DrinkFactory(){
   hot_factories["coffee"] = make_unique<CoffeeFactory>();
   hot_factories["tea"] = make_unique<TeaFactory>();
  }
  unique_ptr<HotDrink> make_drink(const string& name) {
   auto drink = hot_factories[name]->make();
   drink->prepare(200); // oops!
   return drink;
  }
};

这种写法避免了简单工厂模式冗长的switch case,会初始化所有的工厂,通过map来调用特殊类的工厂。

Functional Factory

class DrinkWithVolumeFactory
{
 map<string, function<unique_ptr<HotDrink>()>> factories;
public:
DrinkWithVolumeFactory() {
  factories["tea"] = [] {
      auto tea = make_unique<Tea>(); tea->prepare(200);
      return tea;
  };
}
inline unique_ptr<HotDrink> DrinkWithVolumeFactory::make_drink(const string& name) {
    return factories[name]();
 }
};

这种工厂使用了lambda+function,存储了每个name对应的构建方法。不用再继承很多的派生工厂,看起来非常优雅。

tips:

boost::archive::text_oarchive 可以通过stringstream的方式序列化一个类,很方便


Old style(double check lock)

class Database {
    // same members as before, but then...
    static Database& instance();
private:
    static boost::atomic<Database*> instance;
    static boost::mutex mtx;
};
Database& Database::instance() {
    Database* db = instance.load(boost::memory_order_consume);
    if (!db) {
        boost::mutex::scoped_lock lock(mtx);
    db = instance.load(boost::memory_order_consume);
        if (!db) {
            db = new Database();
      instance.store(db, boost::memory_order_release);
         }
  }
}

C++11

class Database{
protected:
  Database();
public:
  static Database& get() {
    static Database database;
    return database;
  }
  //如果不从静态区分配内存,而是从堆上分配
  static Database& get() {
    static Database* database = new Database();
    return *database;
  }
  Database(Database const&) = delete;
  Database(Database&&) = delete;
  Database& operator=(Database const&) = delete;
  Database& operator=(Database &&) = delete;
}

这个模式实际使用起来比较常见,有个使用方式比较有趣,这里列出来

class PersonAddressBuilder : public PersonBuilderBase {
    typedef PersonAddressBuilder self;
public:
    explicit PersonAddressBuilder(Person& person) : PersonBuilderBase{ person } {}
    self& at(std::string street_address){
      person.street_address = street_address;
        return *this;
    }

  self& with_postcode(std::string post_code) { ... }
  self& in(std::string city) { ... }
};

//使用,赋值属性后返回引用可以持续进行属性赋值
Person p = Person::create()
  .lives().at("123 London Road")
          .with_postcode("SW1 1GB")
          .in("London")
  .works().at("PragmaSoft")
          .as_a("Consultant")
          .earning(10e6);