假设我正在为A类编写一个接口,它保存了B类对象的列表,我希望能够通过A类接口操作该列表。我可以将add_B,remove_B等方法放到A的接口上,但这是很多代码重复(这种情况发生在我程序的很多类中),所以我宁愿返回对列表本身的引用。然而,这会破坏封装 有没有一种标准的方法来处理这种情况?
答案 0 :(得分:1)
没有足够的信息来提供详细的答案,但是从表面上看问题,我认为AddX
/ RemoveX
接口是好的,如果你想限制列表操作或需要维护一些其他约束添加或删除元素时。
但是,如果你经常需要对另一个班级的名单进行复杂的操作,也许它不属于那里?
如果您只是想删除重复,请使用一种mixin类:
template<class T>
class ListOf {
public:
// Public interface only allows adding or removal.
typedef boost::shared_ptr<T> Ptr;
void Add(const Ptr &elem) {
elems_.insert(elem);
}
void Remove(const Ptr &elem) {
elems_.erase(elem);
}
protected:
// Subclass can access container reference.
typedef std::set<Ptr> ElemSet;
ElemSet& Elements() {
return elems_;
}
const ElemSet& Elements() const {
return elems_;
}
private:
ElemSet elems_;
};
class Foo : public Bar, public ListOf<Baz> {
...
};
答案 1 :(得分:1)
以下代码基于代理设计模式。它通过将接口委托给'proxy'对象来保留封装并避免'A'中的庞大接口。
另请注意typedef如何允许将“list”更改为“vector”或其他任何内容。
struct B{};
struct A{
struct containerproxy{
void Add(B *pb);
void Remove(B *pb);
};
friend struct containerproxy;
containerproxy &GetProxy(){return mlprx;}
typedef containerproxy intf;
~A(){
// Code to delete list elements and cleanup the list
}
private:
containerproxy mlprx;
list<B*> mlp;
};
void A::containerproxy::Add(B *pb){ /*code to add pb to mlp*/}
void A::containerproxy::Remove(B *pb){/*code to remove pb from mlp*/}
int main(){
A a;
A::intf &r = a.GetProxy();
B *p = new B;
r.Add(p);
}
答案 2 :(得分:0)
在我目前的发展中,我不得不面对同样的情况。我刚刚通过了对列表的引用。我认为除了你提到的两个选项之外别无选择。也许你应该制作方法来操作整个列表(add_b,remove_b)和一个方法来获取对列表中单个项目的引用以进行项目操作。
BTW:如果你没有使用向量来处理你的对象B列表,那么我建议你这样做。