我想知道你将如何解决这个问题:
我有一节课Foo:
class Foo
{
public:
Foo() { }
~Foo() { }
float member1() { return _member1; }
private:
float _member1;
// other members etc...
}
Run Code Online (Sandbox Code Playgroud)
一个容器类,除其他外,它包含一个指向Foo实例的指针容器
class FooContainer
{
public:
FooContainer() { }
~FooContainer() { }
void addFoo(Foo* f) {_foos.push_back(f);}
private:
boost::ptr_vector<Foo> _foos;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:在运行时我需要向Foo"添加"新的(完全不同的)成员,具体取决于GUI的指令.我可以通过创建这样的两个"装饰器"来解决这个问题:
class Decorator1
{
public:
int alpha() { return _alpha; }
float beta() { return _beta; }
private:
int _alpha;
float _beta;
}
class Decorator2
{
typedef std::complex<float> cmplx;
public:
cmplx gamma() { return _gamma; }
double delta() { return _delta; }
private:
cmplx _gamma;
double _delta;
}
Run Code Online (Sandbox Code Playgroud)
然后我会创建两个不同的Foo实现:
class Foo1 : public Foo, public Decorator1
{ }
class Foo2 : public Foo, public Decorator2
{ }
Run Code Online (Sandbox Code Playgroud)
并根据GUI命令使用每一个.但是这样的改变将通过我的所有代码传播,并会迫使我建立两个不同的版本,使用每个类Foo1和Foo2(如我不得不创建FooContainer1和FooContainer2).
一种不那么具有侵入性的方法就是创造
class Bar: public Foo, public Decorator1, public Decorator2
{ }
Run Code Online (Sandbox Code Playgroud)
并使用它代替Foo.在这种情况下,我会打电话给我只能从需要的功能Decorator1和Decorator2而忽略其他,但这似乎违背良好的面向对象技术.
关于这个问题的任何建议?
你为什么不使用像这样的简单多态?
class Foo
{
public:
Foo() { }
virtual ~Foo() { }
float member1() { return _member1; }
private:
float _member1;
// other members etc...
}
class Foo1 : public Foo
{
public:
int alpha() { return _alpha; }
float beta() { return _beta; }
private:
int _alpha;
float _beta;
}
class Foo2 : public Foo
{
typedef std::complex<float> cmplx;
public:
cmplx gamma() { return _gamma; }
double delta() { return _delta; }
private:
cmplx _gamma;
double _delta;
}
class FooContainer
{
public:
FooContainer() { }
~FooContainer() { }
void addFoo(Foo* f) {_foos.push_back(f);}
private:
boost::ptr_vector<Foo> _foos;
}
Run Code Online (Sandbox Code Playgroud)
然后客户端代码不需要更改.根据GUI命令,您可以创建Foo1或Foo2并将其添加到单个容器中.如有必要,可以使用Foo指针上的dynamic_cast转换为Foo1或Foo2.但是,如果您已正确编写客户端代码,则不需要这样做.