闲谈依赖倒置原则——基于UI动画框架

15 篇文章 0 订阅
9 篇文章 0 订阅

  前面几篇文章讨论了UI动画框架中使用的几个关键的设计模式,框架中还有一些简单的创建模式,我没有说“工厂模式”,意味着并没有严格按照“工厂模式”的定义来实现,而是简单地封装创建过程,这对于框架中的业务已经足够了。
  关于设计模式的讨论就告一段落了,本文聊一聊设计模式的原则之一:“依赖倒置”原则。

1. 依赖倒置原则

  先看一下定义:

  • 高层模块不应该依赖低层模块,两者都应该依赖抽象
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

这定义,看起来好学术!能唬住不少人,至少是唬住了当年的我。坦白说,我一直都没能透彻理解上面的三句话,感觉这3句话就是废话。一个合格的程序猿不会干“高层”直接依赖“低层”的勾当,就算是在用C写代码的时代,一般也会用最基本的封装手段,来将底层的实现细节隐藏在简单的接口(函数)背后;所以,合格的程序猿也不会干“抽象”依赖“细节”的勾当。

  很抱歉,由于我没能透彻理解“依赖倒置”原则,因此接下来,我不打算再详细讨论该原则,后面接着讨论“抽象依赖”原则以及“针对接口编程”。

2. 抽象依赖原则

  我没有给出该原则的定义,我就直接拿动画框架中策略类和窗口类之间的关系来解释这个原则:

在这里插入图片描述

  Window类是CEGUI中所有窗口的基类,从Window类派生的窗口类不下十个,比如:FrameWindow、RichEdit、各类Button等。Window类作为窗口类的抽象,提供了很多通用的接口,比如:

virtual bool isHit(const Vector2f& position, const bool allow_disabled = false) const;
virtual void update(float elapsed);
virtual void updateSelf(float elapsed);

这些通用接口都是抽象接口,由各具体窗口提供适合自身的具体行为。我们的动画框架,为Window类增加了一个IStrategy类型的指针,从而为Window类赋予动画行为。而IStrategy继承体系中的各类具体策略通过参数引用Window类,从而将自身的动画行为施加到具体的窗口上。

  从图中可以看出,FrameWindow、RichEdit甚至其基类Window,并不知晓MoveStrategy、FadeStrategy等具体策略类的存在、而这些策略也不知晓FrameWindow、RichEdit等具体窗口类的存在。窗口类面对的是抽象的策略类IStrategy,它仅仅使用抽象策略类的接口,如IsFinishedRunRestore

void Window::updateSelf(float elapsed)
{
    ... ...

    // 动画处理
    if (d_aniStrategy && d_parent->isVisible())
    {
        d_aniStrategy->Run(*this);
        if (d_aniStrategy->IsFinished(*this))
        {        
            d_aniStrategy->Restore(); // 回收到策略池中
            d_aniStrategy = 0;
        }
    }
}

策略类也仅仅依赖于抽象窗口类(Window),两者都仅仅依赖于对方的抽象,而没有依赖任何的实现细节;所有具体的策略对窗口的访问和控制都是通过Window类的接口来实现(代码从略,可参见前文),反之,窗口类也是通过抽象策略类的接口来实现动画效果。所以,自然而然的,我们谈到了“针对接口编程”。

3. 针对接口编程

  其实不用再解释“针对接口编程”了,上面已经说的够清楚了。简单说两句“针对实现编程”的情况。如果窗口类直接调用各具体的策略类,那么窗口类势必持有每一个具体策略类的引用,从而产生对具体策略类的依赖,这就是针对实现编程了。你可以这样理解:IStrategy是抽象,各具体的策略类(派生类)都是实现。在编程的时候,针对IStrategy编程,就是“针对接口编程”,而针对各具体派生类编程,就是“针对实现编程”。

4. 结语

  回过头来,再唠叨两句“依赖倒置原则”。动画框架中,所谓的“高层”、“低层”或者“底层”并没有很明显的界限,很难说Window类和IStrategy类谁是高层模块,谁是底层模块。如果业务真有明显的“高层”和“底层”之分,稍有点设计头脑的人都不会让“高层”的模块依赖“底层”的模块;“抽象不应该依赖细节”就像在说“基类不应该依赖派生类”一样,而“细节应该依赖抽象”就像在说“派生类应该依赖基类”一样。所以,个人感觉,“依赖倒置原则”的定义中除了“两者都应该依赖抽象”这几个字有点意思,其它的都是所谓的大实话。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值