• 面向对象的多态(三)


    这篇文章跟多态无关了,只是对前面的一点扩充。

    上一篇文章说到,为了把A函数作为参数传递给B函数,我们把A函数封装到了C类里面,而让B函数直接接收C类。那么,有没有办法不通过类,直接让一个函数直接接收另一个函数呢?先给一个定义,能接收函数作为输入的函数,称之为高阶函数。现在越来越多的语言开始支持这个特性了(或者说是我孤陋寡闻,现在才知道很多语言支持高阶函数)。

    那么我们试试用高阶函数来重新实现我们的test script。

    我们一直用来做demo的语言,C#,支持一种叫委托(delegate)的类型,委托是一种定义方法签名的类型,可以与具有兼容签名的任何方法关联。 可以通过委托调用方法。委托用于将方法作为参数传递给其他方法。听起来有点晕,我们还是看代码吧。

    delegate void Behavior();

    上面代码我们定义了一个叫Behavior的委托,它可以指向任何不接收任何参数,返回值为void的函数/方法。回想一下,我们的NavigateInXxx()和BackInXxx()是符合条件的。然后我们往上看几行,“委托用于将方法作为参数传递给其他方法”,这不正是我们想做的事情么?

    经过上一次的重构,我们知道,把switch case移除以后,Navigate和Back函数是没必要存在的,所以,这次我直接从test script开始改写。

    void SimpleTestCase(Behavior navigate, Behavior back)
    {
        navigate();   
        ValidateNavigate(); 
        back();
        ValidateBack(); 
    }

    SimpleTestCase(NavigateInIE, BackInIE);     //在IE下测试
    SimpleTestCase(NavigateInFF, BackInFF);     //在Firefox下测试

    我们看看变化最大的是什么?SimpleTestCase的参数类型变成了Behavior,一个委托类型,正是这一变化,让我们可以把NavigateInXxx和BackInXxx函数作为参数传递给了SimpleTestCase。

    那它解决了添加Chrome测试的问题了吗?老样子,我们列出为了支持Chrome要做的事情:

    1、增加(录制)NavigateInChrome方法

    2、增加(录制)BackInChrome方法

    3、增加test script的调用,SimpleTestCase(NavigateInChrome, BackInChrome)

    仍然很好地实现了对扩展开放,对修改关闭。

    可能一个直接的问题来了,两种方法都能实现,哪种更好呢? 这个问题似乎没有标准答案。高阶函数从函数的粒度对重用进行支持,使用起来更加灵活,例如SimpleTestCase,不考虑实用性的话,我完全可以把NavigateInIE和BackInFF作为一组参数传递过去。而面向对象的实现方法就做不到了,但这似乎恰恰是面向对象的初衷所在,定义好一组契约(每个Browser都应该提供一组Navigate和Back方法)让双方遵守,防止出现NavigateInIE和BackInFF这种非法组合。所以问题的关键,在于你重构代码是为了应对什么样的变化。

    就SimpleTestCase的例子而言,以面向对象的方式重构更为适合,因为所有的浏览器,包括将来会增加进来的,都应该实现共同的契约(实现必须的方法,如果有浏览器对象没实现Navigate方法,test case就跑不过去了)。

    而考虑一个更简单的案例,从1-10,我们要做各种类型的计算(加1,减1,平方...),这时候用高阶函数会更灵活。 反过来如果是面向对象的解决办法,那么我们会定义一堆诸如AddOne, SubOne的类,这些类都只有一个Calculate(int i)的方法,从语义表达上看,显得很累赘,不如定义一堆AddOne(int i), SubOne(int i)函数来得清晰。

  • 相关阅读:
    Object.keys方法之详解
    ackbone入门系列(5)路由
    backbone入门系列(4)集合
    backbone入门系列(3)视图
    backbone入门系列(2)模型
    backbone入门系列(1)基本组成部分
    $(document).ready(function(){ })、window.onload=function(){}与(function($){...})(jQuery)的对比和作用
    backbone笔记1,MVC
    用Object.prototype.toString()来检测对象的类型
    Python生成requirements.txt方法
  • 原文地址:https://www.cnblogs.com/woodylic/p/2559122.html
Copyright © 2020-2023  润新知