我想分解一个类,使其与执行某个任务的逻辑分离,以便用户可以按照自己的意愿编写新策略而不会干扰中心模型.所以,我想使用模板化策略类,但不必让策略的用户进行模板化:
class Model {
...
boost::shared_ptr< Strategy < T > > m_pStrategy;
...
public:
template < typename T >
void DoSomething() { m_pStrategy < T > ::DoSomething(); }
};
Run Code Online (Sandbox Code Playgroud)
我希望DoSomething函数不被模板化.有没有其他方法可以实现我想要做的事情?
谢谢.
在我看来,您想要实现的是基于策略的设计.我不知道什么Model和Strategy究竟做什么,但似乎Model是根类,并且Strategy是策略类,用户希望在某些情况下,提供进行特殊处理.这似乎是你保持指向Strategy<T>周围对象的指针的唯一原因,这样你就可以调用它上面的函数.
在这种情况下,您可以像这样设计您的类:
template<class Strategy>
class Model : public Strategy {
public:
void DoSomething()
{
// magic happens (we will fill this in shortly)
};
};
Run Code Online (Sandbox Code Playgroud)
你在Strategy课堂上调用方法来做你的魔法.通过让用户定义他们自己的Strategy类,您可以让他们有机会定义自己的"魔法".您需要对Strategy类将提供的方法至少应用规则,以便您可以调用这些方法Model.
例如,假设Model实际上是某种资源管理器,能够是一个简单的智能指针,或者像Windows Critical Section的资源管理器.让我们重新命名Model,以auto_resource和Strategy将成为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_;
};
Run Code Online (Sandbox Code Playgroud)
您可以使用这样的std::string指针:
typedef auto_resource<std::string*, pointer_release_policy> string_ptr;
string_ptr my_str;
Run Code Online (Sandbox Code Playgroud)
...当my_str从堆栈中掉落时,release将自动调用该方法.
稍后您要添加用于释放Windows互斥锁HANDLE的新策略:
class handle_release_policy
{
public:
template<class Handle> void release(Handle h)
{
CloseHandle(h); // this is a WINAPI function that deallocates the specified resource
};
};
Run Code Online (Sandbox Code Playgroud)
你可以这样使用:
typedef auto_resource<HANDLE, handle_resource_policy> handle_resource;
//... allocate & use the mutex...
handle_resource mutex = CreateMutex(0, 0, 0);
Run Code Online (Sandbox Code Playgroud)
当然,为了充实这一切,您需要添加分配,复制,释放等资源的功能.这是一个完整的工作示例,将所有内容放在一起.我提供了两套策略,一套用于Windows CRITICAL_SECTION,另一套用于SOCKETs:
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;
Run Code Online (Sandbox Code Playgroud)
有关基于策略的设计的更多信息,请参阅Modern C++ Design.
...