指尖世界

分享的乐趣

我组织类时无意间遵守了依赖倒置原则

类别: 观点 更新时间: 2016-03-12

[摘要:我每次最先写一个小项目标时间,皆念把项目中的那些类构造得文雅一些,但末了的代码老是一团糟,那让我很苦楚。我把愿望拜托于计划形式,愿望它能帮我摆脱。遗憾的是,从打仗计划]

我每次开始写一个小项目的时候,都想把项目中的那些类组织得优雅一些,但最后的代码总是一团糟,这让我很痛苦。我把希望寄托于设计模式,希望它能帮我解脱。遗憾的是,从接触设计模式到现在,已经快三年了,我的代码就只出现过单例模式。不过,从今天开始,一切都不一样了,我的代码里多了依赖倒置原则。
在讲依赖倒置原则在我的代码里的具体呈现之前,先整体说一下设计模式六大原则:
(1)单一职责原则。说的是一个类应该只干一件事儿。
(2)里氏替换原则。说的是,程序中用子类对象替换父类对象,不应该改变程序行为。
(3)依赖倒置原则。说的是,高层不应该依赖低层,它们都应该依赖抽象。
(4)接口隔离原则。说的是,一个接口的大小应该设计得刚好,不应该出现一个类去实现一个接口需要实现与自己无关的方法。
(5)迪米特原则。说的是,低耦合高内聚,也就是说,一个类应该尽量只依赖与它的域、方法参数和返回类型类。
(6)开闭原则。说的是,一个程序应该对扩张开发,对修改关闭。(原则中的原则,它是其它原则的目标)
个人认为,在这六个原则里,最难明白的就是依赖倒置原则了,我也是今天刚刚略懂了。接下来,看看我的代码里是怎遵守这个原则的。
我有一个文件工具类,这个类提供遍历以指定文件夹形成的文件树并对遇到的文件及文件夹实施指定的操作的功能。对遇到的文件及文件夹具体实施什么样的操作,现在并不知道,我自然没办法现在就告诉文件工具类现在干嘛,可是不知道具体操作,这个文件工具类没法开始写啊,于是我现在能做的就是告诉文件工具类一个抽象操作,于是我抽象出一个接口:

public interface FileOperate {
    public void action(File file);
}

然后可以开始写文件工具类了:

public class FileTools {
    /** * 单线程后根遍历文件树,对遇到的文件及文件夹执行指定的操作 * * @param startDirectory 起始目录 * @param fileOperate 对目录的操作 * @param fileOperate 对文件的操作 */
    public static void traverse(File startDirectory,
            FileOperate directoryOperate, FileOperate fileOperate) {
        File[] childFiles = startDirectory.listFiles();
        for (File file : childFiles) {
            if (file.isFile()) {
                fileOperate.action(file);
            } else {
                traverse(file, directoryOperate, fileOperate);
            }
        }
        directoryOperate.action(startDirectory);
    }
}

文件工具类写好了,后来,我知道我想删除某个文件树上所有文件名包含index的文件,但是不对遇到的文件夹做任何操作,于是我写了下面两个类,传给FileTools的traverse方法:

public class DoNothing implements FileOperate {

    @Override
    public void action(File file) {

    }

}
public class DeleteIndexFile implements FileOperate {

    @Override
    public void action(File file) {
        String fileName = file.getName();
        if (fileName.contains("index")) {
            file.delete();
        }

    }

}

后来,我又想删除某文件树中的非html文件以及空文件夹。于是,我又写了下面两个类传给FileTools的traverse方法:

public class DeleteEmptyDirectory implements FileOperate {

    @Override
    public void action(File file) {
        if (file.isDirectory()) {
            file.delete();
        }
    }

}
public class DeleteNoneHtmlFile implements FileOperate {

    @Override
    public void action(File file) {
        String fileName = file.getName();
        if (!fileName.endsWith("html")) {
            file.delete();
        }

    }

}

到这里,大家应该发现,FileOperate和FileTools的设计是对扩展开放的,对修改关闭的,它是一个不错的设计。为什么会有这样的结果了,因为它遵守了依赖倒置原则。FileTools依赖FileOperate,DoNothing 等具体实现类也依赖FileOperate,它们都依赖抽象, 高层模块(FileTools)不依赖底层模块(DoNothing )。
我的这个遵守依赖倒置原则的小项目说完了,现在来说说,理解这个原则的难点——倒置体现在哪里?通常情况,是高层依赖底层,就像靠纳税人钱生活的人总是依赖着纳税人,毕竟拿人家的手短,这和FileTools使用具体的操作一样,但是现在FileTools不直接依赖具体操作了,它只是依赖抽象FileOperate,而具体操作也依赖抽象FileOperate,抽象是最高层,于是变成了低层依赖高层了,这类似于我们经常感受不到那些靠纳税人钱活着的人真是如此,因为我们的税是由第三方交的。
最后,我可以说,我的代码变得优雅了一点儿了,设计模式是可以指望的。



感谢关注 V8指尖世界精品文库频道,v8en.com是专门为互联网人打造的学习交流平台,全面满足互联网人工作与学习需求,更多互联网资讯尽在 V8指尖世界!