title: "modern C++ DesignPattern-Part3" date: 2018-04-12T19:08:49+08:00 lastmod: 2018-04-12T19:08:49+08:00 keywords: [設計模式, C++] tags: [設計模式] categori ...
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);
}