2010-06-11 226 views
2

我想分解一個類,使其與執行特定任務的邏輯分離,以便用戶可以根據需要編寫新策略而不會干擾中央模型。所以,我想用模板策略類,但不必有策略的用戶將被templatised:模板策略模式

class Model { 
    ... 
    boost::shared_ptr< Strategy <T> > m_pStrategy; 
    ... 
    public: 
    template < typename T > 
    void DoSomething() { m_pStrategy <T> ::DoSomething(); } 
    }; 

我想不會是模板的DoSomething的功能。有什麼其他方法可以實現我想在這裏做的事情嗎?

謝謝。

+2

您正在參數化'DoSomething'中的* data member *。它甚至如何編譯? 「T」來自「策略< T >」哪裏? – 2010-06-11 11:37:28

回答

7

在我看來,你想要實現的是一個Policy-Based Design。我不確定ModelStrategy是做什麼的,但看起來好像是Model是根類,而Strategy是Policy類,在某些情況下,用戶希望提供該類來執行特殊處理。它也似乎是你保持一個指向Strategy<T>對象的唯一原因是你可以調用它的函數。

在這種情況下,你可以設計你的類是這樣的:

template<class Strategy> 
class Model : public Strategy { 
public: 
void DoSomething() 
{ 
    // magic happens (we will fill this in shortly) 
}; 
}; 

你呼籲Strategy類的方法做你的魔術。通過讓用戶定義他們自己的課程,讓他們有機會定義他們自己的「魔力」。您需要應用規則,至少要提供什麼方法​​,以便您可以調用Model中的這些方法。

例如,假設Model實際上是某種資源管理器,能夠成爲簡單的智能指針,或者其他類似Windows關鍵部分的資源管理器。我們將Model重命名爲auto_resourceStrategy將變爲release_policy,並將負責釋放分配給它的任何資源。在這種情況下,你可能有:

class pointer_release_policy 
{ 
public: 
    template<class Object> void release(Object* obj) { delete obj; } 
}; 

template<class Managed, class release_policy> 
class auto_resource : public release_policy 
{ 
public: 
    // ... ctors etc defined here 
    ~auto_resource() 
    { 
    release_policy::release(managed_); 
    } 
private: 
    Managed managed_; 
}; 

,你可以使用std::string指針這樣的:

typedef auto_resource<std::string*, pointer_release_policy> string_ptr; 
string_ptr my_str; 

...和my_str脫落的堆棧時,該release方法會自動被調用。

以後要添加新的政策發佈的Windows互斥HANDLE S:

class handle_release_policy 
{ 
public: 
    template<class Handle> void release(Handle h) 
    { 
    CloseHandle(h); // this is a WINAPI function that deallocates the specified resource 
    }; 
}; 

您可以使用此正是如此:

typedef auto_resource<HANDLE, handle_resource_policy> handle_resource; 
//... allocate & use the mutex... 
handle_resource mutex = CreateMutex(0, 0, 0); 

當然,爲了充實這一切了你需要添加分配,複製,釋放資源等功能。這是一個完整的工作示例,它將所有內容放在一起我提供了2套的政策,一個用於Windows CRITICAL_SECTION s,而另一個用於SOCKET S:

class SimpleCopyPolicy 
{ 
public: 
    template<class Resource> Resource copy(const Resource& rhs) const { Resource ret = rhs; return ret; } 
protected: 
    ~SimpleCopyPolicy(){}; 
}; 

class CritsecReleasePolicy 
{ 
public: 
    template<class Handle> bool release(Handle& h) 
    { 
     DeleteCriticalSection(&h); 
     return true; 
    } 
protected: 
    ~CritsecReleasePolicy() {}; 
}; 

class CritsecLockPolicy // CRITICAL_SECTION lock/unlock policies 
{ 
public: 
    template<class Handle> bool lock(Handle& h) 
    { 
     EnterCriticalSection(const_cast<CRITICAL_SECTION*>(&h)); 
     return true; 
    } 
    template<class Handle> bool unlock(Handle& h) 
    { 
     LeaveCriticalSection(&h); 
     return true; 
    } 
}; 


class SocketReleasePolicy 
{ 
public: 
    template<class Handle> bool release(Handle h) { return 0 != closesocket(h); } 
protected: 
    ~SocketReleasePolicy(){}; 
}; 

template<class Resource, typename ReleasePolicy, typename CopyPolicy = SimpleCopyPolicy> 
class simple_auto_resource : public ReleasePolicy, public CopyPolicy 
{ 
public: 
    typedef simple_auto_resource<Resource,ReleasePolicy,CopyPolicy> base_type; 

    simple_auto_resource() : res(0) {} 
    simple_auto_resource(const Resource & r) : res(copy(r)) {} 
    ~simple_auto_resource() { if(res) release(res); } 

    void clear() { if(res) release(res); res = 0; } 

    Resource& get() { return res; } 
    const Resource& get() const { return res; } 

    Resource detach() { Resource ret = res; res = 0; return ret; } 

    operator const Resource&() const { return get(); } 
    operator Resource&() { return get(); } 

    base_type& operator=(const Resource& rhs) { clear(); res = copy(rhs); return * this; } 

    template<class Comp> bool operator==(const Comp& rhs) const { return res == (Resource)rhs; } 
    template<class Comp> bool operator!=(const Comp& rhs) const { return res != (Resource)rhs; } 
    template<class Comp> bool operator<(const Comp& rhs) const { return res < (Resource)rhs; } 
private: 
    Resource res; 
}; 

typedef simple_auto_resource<CRITICAL_SECTION, CritsecReleasePolicy> auto_critsec; 
typedef simple_auto_resource<SOCKET,SocketReleasePolicy> auto_socket; 

更多基於策略的設計,見Modern C++ Design

...

+0

謝謝你的回答... :) – SWKK 2010-06-11 14:54:59

+0

@SWKK:我的榮幸,享受。 – 2010-06-11 15:00:45

+0

已經過了2年..但這是好東西。讓我問你一下。 _strategy pattern_與_policy based pattern_有什麼不同?我從你的代碼中看到的一件事是一個不同背景的主題,其中有非常相似的策略算法。套接字,指針和HANDLE發佈策略都適用於不同的上下文:_sockets指針和Handles_。 **我期待的**設計模式是當上下文不變時,但算法/協議是唯一的。所以也許有兩個distink需要**策略模式的許多上下文**以及**策略模式的許多原語** – jaybny 2012-08-02 04:05:41

0

將功能移出class Strategy<T>