DesignPattern-part1
现代c++改变了很多设计模式的实现方式,为了保持与时俱进,阅读了"Design Pattern in Modern C++"这本书,会记录下来在阅读中的一些心得体会,Part1主要包括 工厂模式,建造者模式与单例模式的现代实现
Factory
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的方式序列化一个类,很方便
Singleton
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;
}
Builder
这个模式实际使用起来比较常见,有个使用方式比较有趣,这里列出来
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);