首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板策略模式

模板策略模式
EN

Stack Overflow用户
提问于 2010-06-11 19:33:19
回答 2查看 3.6K关注 0票数 2

我想拆分一个类,这样它就可以从执行某些任务的逻辑中解耦出来,这样用户就可以按照自己的意愿编写新的策略,而不会干扰中心模型。因此,我希望使用模板化的策略类,但不需要将策略的用户模板化:

代码语言:javascript
复制
   class Model {  
     ...  
     boost::shared_ptr< Strategy < T > > m_pStrategy;  
     ...  
     public:  
     template <  typename T  >  
     void DoSomething() { m_pStrategy < T > ::DoSomething(); }  
    };  

我不希望DoSomething函数被模板化。有没有其他方法可以在这里实现我想做的事情?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-06-11 20:46:52

在我看来,您想实现的是一个Policy-Based Design。我不确定ModelStrategy到底做了什么,但似乎Model是根类,而Strategy是策略类,在某些情况下,用户可能希望提供这些类来执行特殊处理。这似乎也是您保留指向Strategy<T>对象的指针的唯一原因,这样您就可以在它上面调用函数。

在这种情况下,您可以这样设计您的类:

代码语言:javascript
复制
template<class Strategy> 
class Model : public Strategy {  
 public:  
 void DoSomething() 
 { 
    // magic happens (we will fill this in shortly)
 };
};  

您可以调用Strategy类上的方法来施展魔法。通过让用户定义他们自己的Strategy类,您就给了他们定义自己的“魔力”的机会。您至少需要应用Strategy类将提供的方法的规则,以便可以在Model中调用这些方法。

例如,假设Model实际上是某种资源管理器,可以是一个简单的智能指针,也可以是Windows Critical Section的资源管理器。让我们将Model重命名为auto_resourceStrategy将成为release_policy,并将负责释放分配给它的任何资源。在这种情况下,您可能会有:

代码语言:javascript
复制
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指针,如下所示:

代码语言:javascript
复制
typedef auto_resource<std::string*, pointer_release_policy> string_ptr;
string_ptr my_str;

...and当my_str退出堆栈时,将自动调用release方法。

稍后,您需要添加一个用于释放Windows mutex HANDLE的新策略:

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

你可以这样使用它:

代码语言:javascript
复制
typedef auto_resource<HANDLE, handle_resource_policy> handle_resource;
//... allocate & use the mutex...
handle_resource mutex = CreateMutex(0, 0, 0);

当然,为了充实这一切,你需要添加分配、复制、释放资源等功能。这是一个完整的工作示例,它将所有内容放在一起。我提供了两套策略,一套针对CRITICAL_SECTION,另一套针对SOCKET

代码语言:javascript
复制
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

..。

票数 7
EN

Stack Overflow用户

发布于 2010-06-11 19:35:52

将函数移出class Strategy<T>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3022324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档