欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過c++11改進我們的模式之改進命令模式

 更新時間:2013年11月10日 10:13:59   作者:  
這篇我要講的是如何使用c++11改進命令模式,感興趣的朋友可以看下

模式雖然精妙,卻難完美,比如觀察者模式中觀察者生命周期的問題;比如訪問者模式中循環(huán)依賴的問題等等;其它很多模式也存在這樣那樣的一些不足之處,如使用場景受限、實現(xiàn)復雜、不夠簡潔、不夠通用等。但我覺得不足之處大都是可以采取一些手法去彌補去改進的,比如用c++11的新特性來改進。因此,便有了c++11改進我們的模式這個系列。這次我要講的是如何使用c++11改進命令模式。關于命令模式

  命令模式的作用是將請求封裝為一個對象,將請求的發(fā)起者和執(zhí)行者解耦,支持對請求排隊以及撤銷和重做。它的類圖如下:


  由于將請求都封裝成一個個命令對象了,使得我們可以集中處理或者延遲處理這些命令請求,而且不同的客戶對象可以共享這些命令,還可以控制請求的優(yōu)先級、排隊、支持請求命令撤銷和重做等等。命令模式的這些好處是顯而易見的,但是,在實際使用過程中它的問題也暴露出來了。隨著請求的增多,請求的封裝類--命令類也會越來越多,尤其是GUI應用中,請求是非常多的。越來越多的命令類會導致類爆炸,難以管理。關于類爆炸這個問題,GOF很早就意識到了,他們提出了一個解決方法:對于簡單的不能取消和不需要參數(shù)的命令,可以用一個命令類模板來參數(shù)化該命令的接收者,用接收者類型來參數(shù)化命令類,并維護一個接收者對象和一個動作之間的綁定,而這一動作是用指向同一個成員函數(shù)的指針存儲的。具體代碼是這樣的:
簡單命令類的定義:

構造器存儲接收者和對應實例變量中行為。Execute操作實施接收者的這個動作。

為創(chuàng)建一個調用MyClass類的一個實例上的Action行為的Command對象,僅需要如下代碼:

  通過一個泛型的簡單命令類來避免不斷創(chuàng)建新的命令類,是一個不錯的辦法,但是,這個辦法不完美,即它只能是簡單的命令類,不能對復雜的,甚至所有的命令類泛化,這是它的缺陷,所以,它只是部分的解決了問題。我想我可以改進這個辦法缺陷,完美的解決類爆炸的問題。在c++11之前我不知道有沒有人解決過這個問題,至少我沒看到過?,F(xiàn)在可以通過c++11來完美的解決這個問題了。

c++11改進命令模式

  要完美的解決命令模式類爆炸問題的關鍵是如何定義個通用的泛化的命令類,這個命令類可以泛化所有的命令,而不是GOF提到的簡單命令。我們再回過頭來看看GOF中那個簡單的命令類的定義,它只是泛化了沒有參數(shù)和返回值的命令類,命令類內(nèi)部引用了一個接收者和接收者的函數(shù)指針,如果接收者的行為函數(shù)指針有參數(shù)就不能通用了,所以我們要解決的關鍵問題是如何讓命令類能接受所有的成員函數(shù)指針或者函數(shù)對象。
  有沒有一個能接受所有成員函數(shù)、普通函數(shù)和函數(shù)對象的類呢?有,在c++11中可以有,我上一篇博文中提到了一個萬能的函數(shù)包裝器,它可以接受所有的函數(shù)對象、fucntion和lamda表達式,它行不行呢?不行,因為它還不夠完美,它還不能接受成員函數(shù)呢,所以它還不是真正的萬能的函數(shù)包裝器。我打算在它的基礎上再擴展一下,讓它為一個真正的萬能的函數(shù)包裝器。

  接受function、函數(shù)對象、lamda和普通函數(shù)的包裝器:

復制代碼 代碼如下:

template< class F, class... Args, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
void Wrap(F && f, Args && ... args)
{
return f(std::forward<Args>(args)...);
}

接受成員函數(shù)的包裝器:

復制代碼 代碼如下:

template<class R, class C, class... DArgs, class P, class... Args>
void Wrap(R(C::*f)(DArgs...), P && p, Args && ... args)
{
return (*p.*f)(std::forward<Args>(args)...);
}

  通過重載的Wrap讓它能接收成員函數(shù)。這樣一個真正意義上的萬能的函數(shù)包裝器就完成了?,F(xiàn)在再來看,它是如何應用到命令模式中,完美的解決類爆炸的問題。

  一個通用的泛化的命令類:

復制代碼 代碼如下:

template<typename R=void>
struct CommCommand
{
private:
std::function < R()> m_f;

public:
template< class F, class... Args, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
void Wrap(F && f, Args && ... args)
{
m_f = [&]{return f(std::forward<Args>(args)...); };
}

template<class R, class C, class... DArgs, class P, class... Args>
void Wrap(R(C::*f)(DArgs...) const, P && p, Args && ... args)
{
m_f = [&, f]{return (*p.*f)(std::forward<Args>(args)...); };
}

// non-const member function
template<class R, class C, class... DArgs, class P, class... Args>
void Wrap(R(C::*f)(DArgs...), P && p, Args && ... args)
{
m_f = [&, f]{return (*p.*f)(std::forward<Args>(args)...); };
}

R Excecute()
{
return m_f();
}
};

測試代碼:

復制代碼 代碼如下:

struct STA
{
int m_a;
int operator()(){ return m_a; }
int operator()(int n){ return m_a + n; }
int triple0(){ return m_a * 3; }
int triple(int a){ return m_a * 3 + a; }
int triple1() const { return m_a * 3; }
const int triple2(int a) const { return m_a * 3+a; }

void triple3(){ cout << "" <<endl; }
};

int add_one(int n)
{
return n + 1;
}

void TestWrap()
{

CommCommand<int> cmd;
// free function
cmd.Wrap(add_one, 0);

// lambda function
cmd.Wrap([](int n){return n + 1; }, 1);

// functor
cmd.Wrap(bloop);
cmd.Wrap(bloop, 4);

STA t = { 10 };
int x = 3;
// member function
cmd.Wrap(&STA::triple0, &t);
cmd.Wrap(&STA::triple, &t, x);
cmd.Wrap(&STA::triple, &t, 3);

cmd.Wrap(&STA::triple2, &t, 3);
auto r = cmd.Excecute();

CommCommand<> cmd1;
cmd1.Wrap(&Bloop::triple3, &t);
cmd1.Excecute();
}

我們在通用的命令類內(nèi)部定義了一個萬能的函數(shù)包裝器,使得我們可以封裝所有的命令,增加新的請求都不需要重新定義命令了,完美的解決了命令類爆炸的問題。

相關文章

  • C語言實現(xiàn)括號配對的方法示例

    C語言實現(xiàn)括號配對的方法示例

    本文主要介紹了C語言實現(xiàn)括號配對的方法示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++深入刨析muduo中的抽象類Poller

    C++深入刨析muduo中的抽象類Poller

    muduo網(wǎng)絡庫中Poller類是一個抽象類,用戶使用PollPoller或者EPollPoller類,下面跟隨小編一起來詳細了解一下
    2022-04-04
  • 使用VC6.0對C語言程序進行調試的基本手段分享

    使用VC6.0對C語言程序進行調試的基本手段分享

    這篇文章主要介紹了用VC6.0開發(fā)c語言程序的時候調試代碼的一些小技巧,需要的朋友可以參考下
    2013-07-07
  • C++ Clock類模擬實現(xiàn)鬧鐘運行

    C++ Clock類模擬實現(xiàn)鬧鐘運行

    這篇文章主要為大家詳細介紹了C++ Clock類模擬實現(xiàn)鬧鐘運行,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 應用程序操作NorFlash示例代碼分享(norflash接口使用方法)

    應用程序操作NorFlash示例代碼分享(norflash接口使用方法)

    相對于操作NandFlash,操作NorFlash相對簡單,因為基本不需要考慮壞塊,NorFlash也沒有OOB區(qū)域,也跟ECC沒有關系。讀寫擦除相對容易,下面看個例子吧
    2013-12-12
  • C/C++指針介紹與使用詳解

    C/C++指針介紹與使用詳解

    不知從何時起對你一眼萬年,從此,每一天被賦予了特別的意義。時隔多年,依然揮之不去是你------指針!?。”酒袔缀鯏?shù)據(jù)類型只用了int,但是float、double等也是可以的
    2022-08-08
  • QT實現(xiàn)簡單五子棋游戲

    QT實現(xiàn)簡單五子棋游戲

    這篇文章主要為大家詳細介紹了QT實現(xiàn)簡單五子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • C語言中棧的兩種實現(xiàn)方法

    C語言中棧的兩種實現(xiàn)方法

    棧的實現(xiàn)方式有兩種,一種方法是使用指針,而另一種方法則是使用數(shù)組,這篇文章主要介紹了C語言中棧的兩種實現(xiàn)方法,需要的朋友可以參考下
    2021-08-08
  • C++一個函數(shù)如何調用其他.cpp文件中的函數(shù)

    C++一個函數(shù)如何調用其他.cpp文件中的函數(shù)

    這篇文章主要介紹了C++一個函數(shù)如何調用其他.cpp文件中的函數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法

    詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法

    這篇文章主要介紹了詳解C++編程中向函數(shù)傳遞引用參數(shù)的用法,包括使函數(shù)返回引用類型以及對指針的引用,需要的朋友可以參考下
    2016-01-01

最新評論