• 条款35:考虑virtual函数以外的其他选择


    1、考虑virtual函数以外的其他选择是什么意思?

    大多时候,我们会自然而然的想到使用virtual手法来塑模现实中的类。但是,实际上也有别的方案可以替代virtual手法的,即:考虑virtual函数以外的其他选择。下面介绍的便是几种可以替代virtual的方案。

    2、第一种方案:通过Non-Virtual Interface (NVI)手法实现Template Method 模式

    (1)Non-Virtual Interface 是Template Method 设计模式的一个独特的表现形式。
    class GameCharacter {
    public:
        //1、派生类不可改变的算法骨架
        int healthValue() const
        {
            ...//做一些事前工作
            int retVal = doHealthValue();//核心点
            ...//做一些事后工作
            return retVal;
        }
    private:
    	//2、派生类可以改变的算法细节
        virtual int doHealthValue() const //derived class 可以重新定义它。
        {
            ...//缺省计算,计算健康指数
        }
    };
    
    (2)这里把non-virtual的函数 healthValue()称为doHealthValue()函数的外覆器。

    这个实现方法的优点:可以在核心点前做准备工作,和核心点后做善后工作。

    (3)关于对派生类对象中重新定义 private virtual函数的担心
    • 派生类有权利决定实算法的某一步的具体细节
    • 派生类无权决定派生类实现的步骤和时机(这些由基类决定。)
    • 这是合情合理的,因此不必担心。
    (4)virtual函数的访问控制
    • NVI手法中,virtual函数可以是private的
    • NVI手法中,virtual函数也可以是protected的。这样的写法使得派生类可以调用其父类中的对应的函数。
    • NVI手法中,virtual函数不可以是public的。

    注意:准备工作可以是:锁定互斥器、验证class约束条件、验证函数先决条件等等。善后工作可以是:解除互斥器锁定、验证函数的事后条件、再次验证class约束条件等等。

    3、第二种方案:通过Function Pointers完成Strategy模式

    (1)具体做法

    在游戏角色类中添加一个指针,指向一个计算健康指数的函数。

    (2)优点

    通过Funtion Pointers完成Strategy与使用virtual函数实现的比较:

    • 同一人物类型的不同实体可以有不同的健康计算函数。
    • 某个已知人物的健康指数极端函数可以在运行期变更。

    4、第三种方案:通过tr1::function完成Strategy模式(使用函数对象,而不是使用函数指针)

    (1)实现方法:

    上面的方法是让游戏角色类拥有一个指向函数的指针。而这个方案是让游戏角色类拥有一个像函数一样的函数对象。

    (2)优点:
    • 这种方案比上述方案的效果更好,因为函数对象允许我们做的事更多。可以调用任何兼容函数计算健康指数。

    5、第四种方案:传统的Strategy模式

    (1)传统的Strategy的做法是:
    • 设计一个游戏角色类的继承体系,其中可以派生多个类。并且在其基类中包含一个指向计算健康指数类的指针。
    • 将计算健康指数设计成一个继承体系,其中可以派生多个类。
    (2)优点:
    • 设计模式容易辨认。
    • 增加新的健康指数计算类比较容易,只需要在健康指数继承体系中派生一个新的计算类即可。

    6、二、三、四方案存在的问题

    (1)实现方案存在的问题

    实际上也就是说,健康指数计算函数不再是游戏角色类的成员函数了,这也意味着他们不能直接访问游戏角色类的成员了。

    (2)解决上述问题的方法:

    弱化游戏角色类的封装,这也是这种替代方案的缺点,这是下面Strategy设计模式都要需要面临的问题。
    方案一:游戏角色类可以将该函数声明为友元。
    方案二:将游戏角色类的某些成员声明为public。

    (3)三种方案的缺点

    弱化了封装。

  • 相关阅读:
    查找字符串中特定字符最后出现的位置
    C# List中的ForEach
    tensorflow中一个矩阵和一个向量相加
    Hibernate-ORM:16.Hibernate中的二级缓存Ehcache的配置
    Hibernate-ORM:15.Hibernate中的Criteria查询
    Hibernate-ORM:14.Hibernate中的命名查询
    Hibernate-ORM:12.Hibernate中的多对多关联关系
    Hibernate-ORM:10.Hibernate中的分页
    Hibernate-ORM:09.Hibernate中的getCurrentSession()
    Hibernate-ORM:08.Hibernate中的投影查询
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764189.html
Copyright © 2020-2023  润新知