【发布时间】:2015-08-14 13:47:34
【问题描述】:
概述
技术问题是当前的设计似乎需要一个用于 C++ 模板工作者类的抽象工厂,据我所知,这是不可能的。因此,我需要一个替代解决方案来防止客户端依赖于工作人员的实现细节以及来自任何特定客户端环境的工作人员。
环境
我有一个Worker 类,它在内部需要一个容器类C 来记忆处理信息。处理信息组织在BufferType 结构中,因此Worker 在内部处理C< BufferType > 类型的成员。另一方面,我们不希望Worker 的客户知道Worker::BufferType,这反映了Worker 的API 无关的实现细节可能会随着时间而改变。
C 是一个抽象类,根据实际环境(例如数据库)具有不同的容器功能实现,这一事实使情况变得复杂。显然,我们不想让Worker 知道这一点,它应该在任何有C 实现的环境中工作。
由于我没有太多编写工厂的经验,所以我继续写了以下内容:
这些是我必须处理的容器:
template <class T>
class C {
// container interface
};
template <class T>
class CImpl : public C<T> {
// implements C's interface
};
这就是我希望实现Worker 类的方式:
class Worker {
public:
Worker( AbstractCFactory& f ) : _f( &f ), _buffer( NULL ) {}
void doSomething() {
_buffer = _f->create<BufferType>( );
// ... do something with _buffer
}
private:
AbstractCFactory* _f;
typedef struct { int someInfo; } BufferType;
C< BufferType >* _buffer;
};
但是,就工厂而言,这将需要以下内容:
class AbstractCFactory {
public:
template <class T>
virtual C< T >* create() = 0;
};
class ConcreteCFactory : public AbstractCFactory {
public:
template <class T>
virtual C< T >* create() {
return new CImpl< T >();
}
};
虽然我认为这是一个很棒的设计,但编译器并不那么热情,并提醒我模板方法不能是虚拟的。现在想来,这是有道理的——如果工厂类型仅在运行时确定,编译器无法知道为工厂中的模板方法生成哪些代码。
丑陋的解决方法
首先,我将工厂实现为模板以允许虚拟create() 函数:
template <class T>
class AbstractCFactory {
public:
virtual C< T >* create() = 0;
};
template <class T>
class ConcreteCFactory : public AbstractCFactory {
public:
virtual C< T >* create() {
return new CImpl< T >();
}
};
然后,我将BufferType移动到Worker的公共接口,允许客户端创建一个ConcreteCFactory< Worker::BufferType >实例传递给Worker的构造函数。
class Worker {
public:
typedef struct { int someInfo; } BufferType;
Worker( AbstractCFactory< BufferType >& f ) : _f( &f ), _buffer( NULL ) {}
void doSomething() {
_buffer = _f->create( );
// ... do something with _buffer
}
private:
AbstractCFactory< BufferType >* _f;
C< BufferType >* _buffer;
};
显然,我的解决方法不是真正的解决方案,因为它仍然通过将 Worker (BufferType) 的私有实现细节暴露给公共接口来引入不良的客户端依赖性。
问题
是否有不强迫我打破封装的适当解决方案,即保持Worker 独立于CImpl 和客户端独立于Worker::BufferType?
【问题讨论】:
-
我认为有一些可能的解决方案。但我不清楚你的系统的公共接口是什么。 BufferType 的声明是否应该在 public .h 中声明 Worker 类?
-
不,不应该,因为它代表了一种数据结构,仅供
Worker在内部使用,不应向公共 API 公开。在我的“丑陋解决方法”中,我不得不将它移到那里,以便客户端能够生成正确专业化的CImpl,但这正是我在那里使用“丑陋”一词的原因。
标签: c++ templates abstract-factory