开发者社区> 问答> 正文

在需要给每个类增加一个新操作时,成员函数实现方式和访问者实现方式有何区别?

在需要给每个类增加一个新操作时,成员函数实现方式和访问者实现方式有何区别?

展开
收起
不吃核桃 2024-07-31 13:27:10 17 0
2 条回答
写回答
取消 提交回答
  • 成员函数实现方式需要给类层级结构的每个类增加一个实现,这需要修改原来的代码,不符合开闭原则。而访问者实现方式则只需新建一个访问者,完全不影响原来的代码,因此在这种情况下,访问者实现方式更优。

    2024-07-31 14:01:39
    赞同 2 展开评论 打赏
  • 技术浪潮涌向前,学习脚步永绵绵。

    当需要给每个类增加一个新操作时,有两种常见的实现方式:成员函数实现方式和访问者模式实现方式。这两种方式各有优缺点,适用于不同的场景。下面我们来具体分析这两种实现方式的区别。

    成员函数实现方式

    在成员函数实现方式中,你需要直接在类内部添加新的成员函数来实现所需的功能。这种方式是最直观和最直接的方法。

    优点

    • 易于实现:只需在每个类中添加一个新的成员函数即可。
    • 封装性好:新操作被封装在类内部,可以很好地隐藏实现细节。

    缺点

    • 类的职责增加:每次添加新操作都会增加类的复杂度,可能会导致类变得臃肿。
    • 难以扩展:如果需要对所有类都增加相同的操作,那么就需要修改所有的类,这在大型项目中是非常繁琐的工作。
    • 违反开闭原则:修改类本身会违反“对扩展开放,对修改关闭”的原则。

    访问者模式实现方式

    访问者模式是一种行为设计模式,它允许你向现有的类结构中添加新的操作,而不必修改这些类。这种模式通过定义一个包含多个访问方法的访问者接口来实现,每个具体的访问者类实现了这个接口,并针对每个具体的类提供一个访问方法。

    优点

    • 易于扩展:可以通过增加新的访问者类来添加新的操作,无需修改现有的类。
    • 符合开闭原则:对现有类结构的扩展是通过增加新的访问者类实现的,而不是修改原有的类,这样就遵守了“对扩展开放,对修改关闭”的原则。
    • 职责分离:操作逻辑与对象结构分离,使得代码更清晰,也更容易维护。

    缺点

    • 增加了系统复杂性:需要引入访问者接口和一系列访问者类,增加了系统的复杂性和理解成本。
    • 破坏封装性:访问者需要访问对象的内部状态,这可能会破坏对象的封装性。
    • 类型依赖:访问者模式通常需要依赖于对象的具体类型,这可能导致更多的类型检查。

    实现示例

    假设我们有一个简单的类层次结构,包括 Shape 抽象基类和两个派生类 CircleSquare

    成员函数实现方式

    #include <iostream>
    
    class Shape {
    public:
        virtual void draw() const = 0;
    };
    
    class Circle : public Shape {
    public:
        void draw() const override {
            std::cout << "Drawing a circle." << std::endl;
        }
    };
    
    class Square : public Shape {
    public:
        void draw() const override {
            std::cout << "Drawing a square." << std::endl;
        }
    };
    
    // 新增成员函数
    void Shape::highlight() const {
        std::cout << "Highlighting shape." << std::endl;
    }
    

    访问者模式实现方式

    #include <iostream>
    
    class Shape {
    public:
        virtual void accept(Visitor* visitor) const = 0;
    };
    
    class Visitor {
    public:
        virtual void visit(const Circle& circle) = 0;
        virtual void visit(const Square& square) = 0;
    };
    
    class Circle : public Shape {
    public:
        void draw() const {
            std::cout << "Drawing a circle." << std::endl;
        }
    
        void accept(Visitor* visitor) const override {
            visitor->visit(*this);
        }
    };
    
    class Square : public Shape {
    public:
        void draw() const {
            std::cout << "Drawing a square." << std::endl;
        }
    
        void accept(Visitor* visitor) const override {
            visitor->visit(*this);
        }
    };
    
    class HighlightVisitor : public Visitor {
    public:
        void visit(const Circle& circle) override {
            std::cout << "Highlighting a circle." << std::endl;
        }
    
        void visit(const Square& square) override {
            std::cout << "Highlighting a square." << std::endl;
        }
    };
    

    选择哪种实现方式取决于项目的具体情况。如果你预计未来不会频繁地增加新的操作,并且类结构相对稳定,那么直接使用成员函数的方式可能更为合适。相反,如果你预期会有较多的新操作加入,并且希望保持类结构的稳定性,那么访问者模式可能是更好的选择。

    2024-07-31 13:37:10
    赞同 2 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载