title: "modern C++ DesignPattern-Part3" date: 2018-04-12T19:08:49+08:00 lastmod: 2018-04-12T19:08:49+08:00 keywords: [设计模式, C++] tags: [设计模式] categories: []
结构式设计模式的最后两个,享元模式:实现对象共享,减少内存开销;代理模式,提供相同接口的代理
flyweight
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。boost::flyweight使用:
struct User2 { flyweight<string> first_name, last_name; //类似一个缓存 User2(const string &first_name, const string &last_name) : first_name(first_name), last_name(last_name) {} }; void boost_flyweight() { User2 user1{"John", "Smith"}; User2 user2{"Jane", "Smith"}; cout << user1.first_name << endl; cout << boolalpha //std::boolalpha可以把bool变成true/false字符串 << (&user1.first_name.get() == &user2.first_name.get()) << endl; cout << boolalpha << (&user1.last_name.get() == &user2.last_name.get()) << endl; }
示例:
class FormattedText { //用来记录是否被复用的单元 string plain_text; bool *caps; public: explicit FormattedText(const string &plainText) : plain_text{plainText} { caps = new bool[plainText.length()]; memset(caps, 0, plain_text.length()); } ~FormattedText() { delete[] caps; } void capitalize(int start, int end) { for (int i = start; i <= end; ++i) caps[i] = true; } friend std::ostream &operator<<(std::ostream &os, const FormattedText &obj) { string s; for (int i = 0; i < obj.plain_text.length(); ++i) { char c = obj.plain_text[i]; s += (obj.caps[i] ? toupper(c) : c); } return os << s; } }; class BetterFormattedText { public: struct TextRange { int start, end; bool capitalize, bold, italic; bool covers(int position) const { return position >= start && position <= end; } }; TextRange &get_range(int start, int end) { //每当设置一个被复用的单元,push到vector里面,返回最后一个 formatting.emplace_back(TextRange{start, end}); return *formatting.rbegin(); } explicit BetterFormattedText(const string &plainText) : plain_text{plainText} { } friend std::ostream &operator<<(std::ostream &os, const BetterFormattedText &obj) { string s; for (size_t i = 0; i < obj.plain_text.length(); i++) { auto c = obj.plain_text[i]; for (const auto &rng : obj.formatting) { if (rng.covers(i) && rng.capitalize) c = toupper(c); } s += c; // fixed! } return os << s; } private: string plain_text; vector<TextRange> formatting; };
Proxy
代理模式最经典的是shared_ptr实现,增加了引用计数的同时保持了原有的普通指针接口
Property Proxy
template <typename T> struct Property { T value; Property(const T initialValue) { *this = initialValue; } operator T() { //getter return value; } T operator =(T newValue) { //setter return value = newValue; } }; //usage struct Creature { Property<int> strength{ 10 }; Property<int> agility{ 5 }; }; void property_proxy() { Creature creature; creature.agility = 20; cout << creature.agility << endl; }
主要目的是可以允许 Property<int>
与int的随时转换。
Virtual Proxy
这种非常常见,使用时分两种,eager模式和lazy模式,区别就是lazy模式是在使用的时候才会初始化
struct Image{ virtual ~Image() = default; virtual void draw() = 0; }; struct Bitmap : Image{ Bitmap(const string& filename) { cout << "Loading image from " << filename << endl; } void draw() override { cout << "Drawing image" << endl; } }; struct LazyBitmap : Image { LazyBitmap(const string& filename): filename(filename) {} ~LazyBitmap() { delete bmp; } void draw() override { if (!bmp) bmp = new Bitmap(filename); bmp->draw(); } private: Bitmap* bmp{nullptr}; string filename; }; void draw_image(Image& img) { img.draw(); } void virtual_proxy() { LazyBitmap img{ "pokemon.png" }; draw_image(img); // loaded whether the bitmap is loaded or not draw_image(img); }