C ++中的复合模式

时间:2010-04-26 18:38:09

标签: c++ stl composite

我必须使用类似于电话簿的C ++应用程序:带有STL联系人列表的类议程。关于联系人层次结构,有一个名为Contact(一个抽象的)的基类,以及派生的class Friend and Acquainance(联系方式)。

例如,这些类具有一个名为getName的虚方法,它返回联系人的名称。

现在我必须通过添加另一种类型的联系人公司(来自联系人)实现复合模式,该公司还包含一组联系人(也是STL列表),可以是“叶子”类型(朋友或熟人),或者他们也可以是公司。

因此,公司是复合型。

问题是:如何以及在哪里可以实现STL find_if来搜索具有给定名称的联系人(通过getName函数或建议我使用其他方式)两者之间的“叶子”类型联系在公司集合内?

换句话说,如何使用统一的函数定义遍历树以便找到可能的匹配?

我希望我很清楚......

3 个答案:

答案 0 :(得分:2)

嗯,一种方法:

virtual contact* contact::findContact(std::string name)
{
    if(m_name == name) {return this;}
    return NULL;
}

然后:

contact * Company::findContact(std::string name)
{
    if(!contact::findContact(name) )
    {
        //For each contact in the contact list, findContact(name)
        //If we find something, return that.
        //Otherwise return null.
    }
    return this;
}

您正在做的是让每个节点找到您正在寻找的节点,而不关心它是什么类型的节点(叶子或其他)。然后,每个节点检查自己,对于那些有子节点的人,检查他们的孩子。

答案 1 :(得分:1)

列表是大型联系人的错误类型,因为您可能有O(N)来查找最后一个联系人,甚至找不到联系人。
我建议你使用哈希映射(来自boost / tr1的unordered_map)或常规地图,这样你就可以使用密钥通过ID或其名称找到它们。
听起来公司应该只是一个联系树 您可以找到树实现here 您通过树进行transVase以找到所需的节点。

答案 2 :(得分:0)

“现在我必须通过添加另一种类型的联系人,公司(来自联系人)来实现复合模式,该联系人还包含一组联系人(也是STL列表),它们可以是”叶子“类型(朋友或熟人),或者他们也可以是公司“

您可以为Company创建一个兼容stl的复合迭代器。

class Company : public Contact {
    std::list<Contact *> contactList;

    //snip...other private members
    friend class CompanyIterator;
    friend class ConstCompanyIterator;
  public:

     // nested iterator classes
     class CompanyIterator : public std::iterator<std::forward_iterator_tag, Contact *> {

          friend class Company;
          // pair<>.first is the iterator obtain by calling begin()
          // pair<>.second is the end iterator
          std::stack< std::pair< std::list<Contact *>::iterator, 
                      std::list<Contact *>::iterator> > iters_stack;

          Contact *pCurrentContact;
          Company *pCompany; // This is the top level company which will be iterated.

        public:

          explicit CompanyIterator(Company &c);

          // Required forward iterator methods follow
          CompanyIterator();
          CompanyIterator(const CompanyIterator&);
          CompanyIterator& operator=(const CompanyIterator& other);
          Contact &operator*() const;
          Contact *operator->() const;
          CompanyIterator& operator++();
          CompanyIterator operator++(int);

          bool operator==(const CompanyIterator& x) const;
          bool operator!=(const CompanyIterator& x) const;
     };

     // nested iterator class
     class ConstCompanyIterator : public std::iterator<std::forward_iterator_tag, 
          const Contact *> {

          friend class Company;
          // We use CompanyIterator to implement ConstCompanyIteraor  
           CompanyIterator inner_iter; // fwd operations here,
                                      // using "const_cast<Company *>(this)->method()"
        public:

          explicit ConstCompanyIterator(const Company & dir);

          // This ctor will function as a cast operator, to convert a CompanyIterator
          // into a ConstCompanyIterator
          ConstCompanyIterator(const CompanyIterator &iter);

          // Required forward iterator methods follow
          ConstCompanyIterator();
          ConstCompanyIterator(const ConstCompanyIterator&);
          ConstCompanyIterator& operator=(const ConstCompanyIterator& other);

          const Contact &operator*() const;
          const Contact *operator->() const;

          ConstCompanyIterator& operator++();
          ConstCompanyIterator operator++(int);

          bool operator==(const ConstCompanyIterator& x) const;
          bool operator!=(const ConstCompanyIterator& x) const;
     };

    typedef CompanyIterator iterator;
    typedef ConstCompanyIterator const_iterator;

    iterator begin();
    iterator end();

    const_iterator begin() const;
    const_iterator end() const;

    // snip... other Company public methods
};

对于上面给出的前向迭代器方法的实现,请参阅Github上的Composite Iterator代码。大多数实现都在Directory.cpp中。 github代码用于模拟文件系统的复合模式。类目录是复合。类文件是叶类。类Node是基本组件类。

find_if的仿函数看起来像

 FindIfFunctor {
      std::string name;
    public:
     FindIfFunctor(const std::string& n) : name(n) {} 
     bool operator()(const Contact& c) { return c.getName().compare(name); }
 }; 

最后,find_if代码

 Company c;
 // snip... stuff gets added to company
 string someName("IBM");

 find_if(c.begin(), c.end(), FindIfFunctor(someName));