設計模式 第三周 博覽網

image

singleton 單件模式

image

image

image

示例代碼

class Singleton{
private:   //將拷貝構造函數和默認構造函數置為私有
    Singleton();
    Singleton(const Singleton& other);
public:
    static Singleton* getInstance();
    static Singleton* m_instance;
};

Singleton* Singleton::m_instance=nullptr;

//線程非安全版本
Singleton* Singleton::getInstance() {
    if (m_instance == nullptr) {
        m_instance = new Singleton();
    }
    return m_instance;
}


//線程安全版本,但鎖的代價過高
Singleton* Singleton::getInstance() {
    Lock lock;
    if (m_instance == nullptr) {
        m_instance = new Singleton();
    }
    return m_instance;
}

//雙檢查鎖,但由于內存讀寫reorder不安全
Singleton* Singleton::getInstance() {

    if(m_instance==nullptr){  //判斷是否是寫操作
        //下面三行為鎖寫操作的必須步驟。
        Lock lock;           //鎖后還要檢查一次,鎖后必須進行必須的檢查
        if (m_instance == nullptr) {
            m_instance = new Singleton();
        }
    }
    return m_instance;
}

//C++ 11版本之后的跨平臺實現 (volatile)
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;

Singleton* Singleton::getInstance() {
    Singleton* tmp = m_instance.load(std::memory_order_relaxed);//獲得原子變量
    std::atomic_thread_fence(std::memory_order_acquire);//獲取內存fence
    if (tmp == nullptr) {
        std::lock_guard<std::mutex> lock(m_mutex);
        tmp = m_instance.load(std::memory_order_relaxed);
        if (tmp == nullptr) {
            tmp = new Singleton;
            std::atomic_thread_fence(std::memory_order_release);//釋放內存fence
            m_instance.store(tmp, std::memory_order_relaxed);
        }
    }
    return tmp;
}
image

image

Flyweight 享元模式

image

image

image

實例代碼

class Font {
private:

    //unique object key
    string key;

    //object state
    //....

public:
    Font(const string& key){
        //...
    }
};
class FontFactory{
private:
    map<string,Font* > fontPool;
public:
    Font* GetFont(const string& key){

        map<string,Font*>::iterator item=fontPool.find(key);
        //以共享的方式使用,而不是一直創建對象
        if(item!=footPool.end()){
            return fontPool[key];
        }
        else{
            Font* font = new Font(key);
            fontPool[key]= font;
            return font;
        }

    }
    void clear(){
        //...
    }
};
image

image

image

State 狀態模式

image

原始代碼

enum NetworkState
{
    Network_Open,
    Network_Close,
    Network_Connect,
};

class NetworkProcessor{
    
    NetworkState state;

public:
    
    void Operation1(){
        if (state == Network_Open){

            //**********
            state = Network_Close;
        }
        else if (state == Network_Close){

            //..........
            state = Network_Connect;
        }
        else if (state == Network_Connect){

            //$$$$$$$$$$
            state = Network_Open;
        }
    }

    public void Operation2(){

        if (state == Network_Open){
            
            //**********
            state = Network_Connect;
        }
        else if (state == Network_Close){

            //.....
            state = Network_Open;
        }
        else if (state == Network_Connect){

            //$$$$$$$$$$
            state = Network_Close;
        }
    
    }

    public void Operation3(){

    }
};

重構代碼

//將枚舉類抽象出來
class NetworkState{

public:
    NetworkState* pNext;
    virtual void Operation1()=0;
    virtual void Operation2()=0;
    virtual void Operation3()=0;

    virtual ~NetworkState(){}
};


class OpenState :public NetworkState{
    //狀態只需要一個實例化的對象,所以使用singleton模式
    static NetworkState* m_instance;
public:
    static NetworkState* getInstance(){
        if (m_instance == nullptr) {
            m_instance = new OpenState();
        }
        return m_instance;
    }
//只關注本狀態下的下一個狀態是什么。
    void Operation1(){

        //**********
        pNext = CloseState::getInstance();
    }

    void Operation2(){

        //..........
        pNext = ConnectState::getInstance();
    }

    void Operation3(){

        //$$$$$$$$$$
        pNext = OpenState::getInstance();
    }


};

class CloseState:public NetworkState{ }
//...



//各種狀態下的動作。
class NetworkProcessor{

    NetworkState* pState;

public:
    //虛函數其實就是動態下的ifesle語句
    NetworkProcessor(NetworkState* pState){

        this->pState = pState;
    }

    void Operation1(){
        //...
        pState->Operation1();
        pState = pState->pNext;
        //...
    }

    void Operation2(){
        //...
        pState->Operation2();
        pState = pState->pNext;
        //...
    }

    void Operation3(){
        //...
        pState->Operation3();
        pState = pState->pNext;
        //...
    }

};
image

image

image

image

Memento備忘錄

image

image

image

實例代碼


class Memento //實現狀態快照
{
    string state;
    //..
public:
    Memento(const string & s) : state(s) {}
    string getState() const { return state; }
    void setState(const string & s) { state = s; }
};



class Originator
{   //需要保存的狀態
    string state;
    //....
public:
    Originator() {}
    Memento createMomento() {  //對當前狀態拍照
        Memento m(state);
        return m;
    }
    void setMomento(const Memento & m) {  //恢復快照狀態
        state = m.getState();
    }
};



int main()
{
    Originator orginator;

    //捕獲對象狀態,存儲到備忘錄
    Memento mem = orginator.createMomento();

    //... 改變orginator狀態

    //從備忘錄中恢復
    orginator.setMomento(memento);



}

image

image

image

Composite組合模式

image

image

image

實例代碼

#include <iostream>
#include <list>
#include <string>
#include <algorithm>

using namespace std;
//實現一個接口,可以同時處理葉子節點和樹節點,不管具體數據結構
class Component
{
public:
    virtual void process() = 0;
    virtual ~Component(){}
};

//樹節點
class Composite : public Component{

    string name;
    list<Component*> elements;
public:
    Composite(const string & s) : name(s) {}

    void add(Component* element) {
        elements.push_back(element);
    }
    void remove(Component* element){
        elements.remove(element);
    }

    void process(){

        //1. process current node


        //2. process leaf nodes
        for (auto &e : elements)
            e->process(); //多態調用

    }
};

//葉子節點
class Leaf : public Component{
    string name;
public:
    Leaf(string s) : name(s) {}

    void process(){
        //process current node
    }
};


void Invoke(Component & c){
    //...
    c.process();
    //...
}


int main()
{

    Composite root("root");
    Composite treeNode1("treeNode1");
    Composite treeNode2("treeNode2");
    Composite treeNode3("treeNode3");
    Composite treeNode4("treeNode4");
    Leaf leat1("left1");
    Leaf leat2("left2");

    root.add(&treeNode1);
    treeNode1.add(&treeNode2);
    treeNode2.add(&leaf1);

    root.add(&treeNode3);
    treeNode3.add(&treeNode4);
    treeNode4.add(&leaf2);
//處理樹節點和葉子節點具有了一直性。
    process(root);
    process(leaf2);
    process(treeNode3);

}
image

image

Iterator迭代器模式

image

image

image

示例代碼

template<typename T>
class Iterator
{
public:
    virtual void first() = 0;
    virtual void next() = 0;
    virtual bool isDone() const = 0;
    virtual T& current() = 0;
};



template<typename T>
class MyCollection{
    
public:
    
    Iterator<T> GetIterator(){
        //...
    }
    
};

template<typename T>
class CollectionIterator : public Iterator<T>{
    MyCollection<T> mc;
public:
    
    CollectionIterator(const MyCollection<T> & c): mc(c){ }
    
    void first() override {
        
    }
    void next() override {
        
    }
    bool isDone() const override{
        
    }
    T& current() override{
        
    }
};

void MyAlgorithm()
{
    MyCollection<int> mc;
    
    Iterator<int> iter= mc.GetIterator();
    
    for (iter.first(); !iter.isDone(); iter.next()){
        cout << iter.current() << endl;
    }
    
}
image

image

Chain of Resposibility職責連模式

image

image

image

示例代碼

#include <iostream>
#include <string>

using namespace std;

enum class RequestType
{
    REQ_HANDLER1,
    REQ_HANDLER2,
    REQ_HANDLER3
};

class Reqest
{
    string description;
    RequestType reqType;
public:
    Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
    RequestType getReqType() const { return reqType; }
    const string& getDescription() const { return description; }
};

//處理接口
class ChainHandler{

    ChainHandler *nextChain;
    void sendReqestToNextHandler(const Reqest & req)
    {
        if (nextChain != nullptr)
            nextChain->handle(req);
    }
protected:
    virtual bool canHandleRequest(const Reqest & req) = 0;
    virtual void processRequest(const Reqest & req) = 0;
public:
    ChainHandler() { nextChain = nullptr; }
    void setNextChain(ChainHandler *next) { nextChain = next; }


    void handle(const Reqest & req)
    {
        if (canHandleRequest(req))
            processRequest(req);
        else
            sendReqestToNextHandler(req);
    }
};

//具體的處理方法
class Handler1 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER1;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
    }
};

class Handler2 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER2;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
    }
};

class Handler3 : public ChainHandler{
protected:
    bool canHandleRequest(const Reqest & req) override
    {
        return req.getReqType() == RequestType::REQ_HANDLER3;
    }
    void processRequest(const Reqest & req) override
    {
        cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
    }
};

int main(){
    Handler1 h1;
    Handler2 h2;
    Handler3 h3;
    h1.setNextChain(&h2);
    h2.setNextChain(&h3);

    Reqest req("process task ... ", RequestType::REQ_HANDLER3);
    h1.handle(req);
    return 0;
}

image

image

image

Command 命令模式

image

image

image

示例代碼

//命令模式

#include <iostream>
#include <vector>
#include <string>
using namespace std;


class Command
{
public:
    virtual void execute() = 0;
};

class ConcreteCommand1 : public Command  //是一個對象,但是可以表征一種行為
{
    string arg;
public:
    ConcreteCommand1(const string & a) : arg(a) {}
    void execute() override
    {
        cout<< "#1 process..."<<arg<<endl;
    }
};

class ConcreteCommand2 : public Command
{
    string arg;
public:
    ConcreteCommand2(const string & a) : arg(a) {}
    void execute() override
    {
        cout<< "#2 process..."<<arg<<endl;
    }
};


class MacroCommand : public Command  //宏命令
{
    vector<Command*> commands;
public:
    void addCommand(Command *c) { commands.push_back(c); }
    void execute() override
    {
        for (auto &c : commands)
        {
            c->execute();
        }
    }
};



int main()
{

    ConcreteCommand1 command1(receiver, "Arg ###");
    ConcreteCommand2 command2(receiver, "Arg $$$");

    MacroCommand macro;
    macro.addCommand(&command1);
    macro.addCommand(&command2);

    macro.execute();

}
image

image

Visitor訪問器

image

原始代碼

//原始版本
#include <iostream>
using namespace std;

class Visitor;


class Element
{
public:
    virtual void Func1() = 0;
    //添加的新操作 ,更改了基類很不方便
    virtual void Func2(int data)=0;
    virtual void Func3(int data)=0;
    //...

    virtual ~Element(){}
};

class ElementA : public Element
{
public:
    void Func1() override{
        //...
    }

    void Func2(int data) override{
        //...
    }

};

class ElementB : public Element
{
public:
    void Func1() override{
        //***
    }

    void Func2(int data) override {
        //***
    }

};

重構代碼

//Vistor模式,能夠預料到移后會增加行為
//先進行頂層設計
#include <iostream>
using namespace std;

class Visitor;


class Element
{
public:
    virtual void accept(Visitor& visitor) = 0; //第一次多態辨析

    virtual ~Element(){}
};

class ElementA : public Element
{
public:
    void accept(Visitor &visitor) override {
        visitor.visitElementA(*this);
    }


};

class ElementB : public Element
{
public:
    void accept(Visitor &visitor) override {
        visitor.visitElementB(*this); //第二次多態辨析
    }

};
//============================
//在將來增加行為時,進行添加
class Visitor{
public:
    virtual void visitElementA(ElementA& element) = 0;
    virtual void visitElementB(ElementB& element) = 0;

    virtual ~Visitor(){}
};

//==================================

//擴展1
class Visitor1 : public Visitor{
public:
    void visitElementA(ElementA& element) override{
        cout << "Visitor1 is processing ElementA" << endl;
    }

    void visitElementB(ElementB& element) override{
        cout << "Visitor1 is processing ElementB" << endl;
    }
};

//擴展2
class Visitor2 : public Visitor{
public:
    void visitElementA(ElementA& element) override{
        cout << "Visitor2 is processing ElementA" << endl;
    }

    void visitElementB(ElementB& element) override{
        cout << "Visitor2 is processing ElementB" << endl;
    }
};




int main()
{
    Visitor2 visitor;
    ElementB elementB;
    elementB.accept(visitor);// double dispatch 兩次動態辨析

    ElementA elementA;
    elementA.accept(visitor);


    return 0;
}
image

image

image

image

image

Interpreter 解析器

image

示例代碼

//解析器模式
#include <iostream>
#include <map>
#include <stack>

using namespace std;

class Expression {
public:
    virtual int interpreter(map<char, int> var)=0;
    virtual ~Expression(){}
};

//變量表達式
class VarExpression: public Expression {

    char key;

public:
    VarExpression(const char& key)
    {
        this->key = key;
    }

    int interpreter(map<char, int> var) override {
        return var[key];
    }

};

//符號表達式
class SymbolExpression : public Expression {

    // 運算符左右兩個參數
protected:
    Expression* left;
    Expression* right;

public:
    SymbolExpression( Expression* left,  Expression* right):
        left(left),right(right){

    }

};

//加法運算
class AddExpression : public SymbolExpression {

public:
    AddExpression(Expression* left, Expression* right):
        SymbolExpression(left,right){

    }
    int interpreter(map<char, int> var) override {
        return left->interpreter(var) + right->interpreter(var);
    }

};

//減法運算
class SubExpression : public SymbolExpression {

public:
    SubExpression(Expression* left, Expression* right):
        SymbolExpression(left,right){

    }
    int interpreter(map<char, int> var) override {
        return left->interpreter(var) - right->interpreter(var);
    }

};



Expression*  analyse(string expStr) {

    stack<Expression*> expStack;
    Expression* left = nullptr;
    Expression* right = nullptr;
    for(int i=0; i<expStr.size(); i++)
    {
        switch(expStr[i])
        {
            case '+':
                // 加法運算
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new AddExpression(left, right));
                break;
            case '-':
                // 減法運算
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new SubExpression(left, right));
                break;
            default:
                // 變量表達式
                expStack.push(new VarExpression(expStr[i]));
        }
    }

    Expression* expression = expStack.top();

    return expression;
}

void release(Expression* expression){

    //釋放表達式樹的節點內存...
}

int main(int argc, const char * argv[]) {


    string expStr = "a+b-c+d-e";
    map<char, int> var;
    var.insert(make_pair('a',5));  //a=5
    var.insert(make_pair('b',2));  //b=2
    var.insert(make_pair('c',1));  //c=1
    var.insert(make_pair('d',6));  //d=6
    var.insert(make_pair('e',10)); //e=10


    Expression* expression= analyse(expStr);

    int result=expression->interpreter(var);

    cout<<result<<endl;

    release(expression);

    return 0;
}

image

image

image

image

image
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,412評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,514評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,373評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,975評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,743評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,199評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,262評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,414評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,951評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,780評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,527評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,218評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,649評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,889評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,673評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容