2013-05-13 30 views
9

Tôi bị kẹt với một vấn đề trùng lặp mã, liên quan đến mẫu khách truy cập cho một cây. Tình hình hiện tại là như sau: Tôi có một cây, bao gồm hai lớp nút khác nhau, tức là lá và không lá. Ngoài ra, tôi có hai lớp cơ sở khách truy cập trông rất giống nhau, ngoại trừ một lượt truy cập const cây và các cây không phải const khác. Các hành động thực tế mà khách truy cập cụ thể phải làm là độc lập với các loại bê tông của nút. Tôi sẽ đưa ra một ví dụ nhỏ:Mẫu khách truy cập cho các phiên bản const và nonconst của cây

class Visitor; 
class ConstVisitor; 

class Node { 
public: 
    virtual void accept(Visitor&) = 0; 
    virtual void accept(ConstVisitor&) const = 0; 
}; 

class Leaf : public Node { 
    virtual void accept(Visitor& v)  {v.visitLeaf(*this);} 
    virtual void accept(ConstVisitor& cv) {cv.visitLeaf(*this);} 
}; 

class CompoundNode : public Node { 
public: 
    vector<Node*> getChildren() const; 
    virtual void accept(Visitor& v)  {v.visitCompoundNode(*this);} 
    virtual void accept(ConstVisitor& cv) {cv.visitCompoundNode(*this);} 
}; 

class Visitor { 
protected: 
    virtual void processNode(Node& node) = 0; 
public: 
    void visitLeaf(Leaf& leaf) { 
    processNode(leaf); 
    } 
    void visitCompoundNode(CompoundNode& cNode) { 
    processNode(cNode); 
    auto children = cNode.getChildren(); 
    for (auto child : children) 
     child->accept(this); 
    } 
}; 

class ConstVisitor { 
protected: 
    virtual void processNode(Node const& node) = 0; 
public: 
    void visitLeaf(Leaf const& leaf) { 
    processNode(leaf); 
    } 
    void visitCompoundNode(CompoundNode const& cNode) { 
    processNode(cNode); 
    auto children = cNode.getChildren(); 
    for (auto child : children) 
     child->accept(this); 
    } 
}; 

lớp khách bê tông thừa kế hoặc từ Visitor hoặc từ ConstVisitor, tuỳ thuộc vào việc phương pháp processNode của họ có thay đổi các nút đến thăm hay không. Bạn thấy đấy, có rất nhiều sự sao chép mã giữa hai khách truy cập và vì tôi sẽ phải triển khai một chiến lược truyền tải khác, cũng cho cả hai nút const và nonconst, tôi muốn tránh trùng lặp đó. Có khả năng trích xuất mã trùng lặp hay không, tốt nhất là không sử dụng const_cast ở khắp mọi nơi?

Trả lời

11

Bạn có thể xác định một mẫu TVisitor lớp as done dưới đây:

#include <type_traits> 

class Node; 
class CompoundNode; 
class Leaf; 

template<bool isNonConstVisitor> 
class TVisitor 
{ 
    typedef typename std::conditional<isNonConstVisitor, 
     Node, Node const>::type node_type; 

    typedef typename std::conditional<isNonConstVisitor, 
     CompoundNode, CompoundNode const>::type compound_node_type; 

    typedef typename std::conditional<isNonConstVisitor, 
     Leaf, Leaf const>::type leaf_node_type; 

protected: 

    virtual void processNode(node_type& node) = 0; 

public: 

    void visitLeaf(leaf_node_type& leaf) { processNode(leaf); } 

    void visitCompoundNode(compound_node_type& cNode) { 
     processNode(cNode); 
     auto children = cNode.getChildren(); 
     for (auto child : children) { child->accept(*this); } 
    } 
}; 

Và sau đó sử dụng VisitorConstVisitor as type bí danh cho sự khởi tạo của lớp mẫu tương ứng:

typedef TVisitor<true> Visitor; 
typedef TVisitor<false> ConstVisitor; 
+0

Cảm ơn, đó là nhanh và giải pháp sạch. Tôi hy vọng các đồng nghiệp của tôi không ghét các mẫu quá nhiều ;-) –

+0

@ArneMertz: Được rồi, chúc may mắn với dự án của bạn;) –

0

Bạn có thể sử dụng các mẫu :

template<typename NodeType, 
     typename CompoundNodeType, 
     typename LeafType> 
class BaseVisitor { 
protected: 
    virtual void processNode(NodeType& node) = 0; 
public: 
    void visitLeaf(LeafType& leaf) { 
     processNode(leaf); 
    } 
    void visitCompoundNode(CompoundNodeType& cNode) { 
     processNode(cNode); 
     auto children = cNode.getChildren(); 
     for (auto child : children) 
     child->accept(this); 
    } 
}; 

class Visitor: public BaseVisitor<Node, CompoundNode, Leaf> { 
}; 

class ConstVisitor: public BaseVisitor<const Node, const CompoundNode, const Leaf> { 
}; 
Các vấn đề liên quan