深入理解架构中的七大设计原则

在进行软件架构设计的工作时,需要遵循面向对象的设计原则。这些原则同样体现在设计模式和架构模式之中,这些原则不断的被淘汰,也有新的原则加入,正真流传下来的并不多,本文中主要给大家介绍前人总结出来的七种设计原则。他们分别是:单一职责原则、里氏替换原则、开闭原则、依赖注入原则、接口分离原则、迪米特原则、合成复用原则。
在上一篇博客上为大家介绍了单一职责原则,即系统里的一个类应该只有一个单独的职责。相信大家一定体会到了这样做的好处吧,那么这次咱们来聊聊其他设计原则。
先来聊聊里氏替换原则吧,来看下面这段代码:

public class Father {
    public Collection run(HashMap map) {
        System.out.println("Father run.....");
        return map.values();
    }
}
public class Son extends Father{
    public Collection run(Map map) {
        System.out.println("Son run.....");
        return map.values();
    }
}
public class Test {
    public static void main(String[] args) {
        /**
         * 此处的父类对象和子类对象的效果是一样的
         */
        // Father f = new Father();
        Son s = new Son();
        HashMap map = new HashMap();
        // f.run(map);
        s.run(map);
    }
}

看上面的代码,Son类继承自Father类,**并且重载了父类种的run方法,注意v这里并不是重写!**Father类种的run方法的参数是HashMap类型,但是Son中的run方法的参数是Map类型的。为什么可以这样呢????其实不难发现,在一个继承体系中子类的功能应该是父类功能的扩展,而在这里HashMap是Map的子类!!!
接着看test类中的测试代码,你和运行后就会发现s对象和f对象的效果是相同的!!!很神奇吧,其实这就是我接下来要给大家介绍的里氏替换原则,
所谓里氏替换原则的核心思想就是在任何父类对象出现的地方都就可以用他的子类对象来代替,并且效果是相同的。
该原则关注的是怎样良好的使用继承,不滥用继承,他是继承使用的基石。简单来说里氏替换原则就是为了良好的继承定义了一个规范可以分为4层含义:
第一:子类必须完全实现父类的方法,
第二:子类应该有自己的特性,但是也不影响父类的功能
第三:覆盖或者实现父类方法的时候,该方法接收的参数类型可以被放大,即上述代码中的描述,个人认为这一点最有意思,所以写了示例代码
第四:覆盖或者实现父类方法的时候,该方法接收的参数类型可以被缩小。和第三点相似
好了,接下来聊聊下一个原则,依赖注入原则。
所谓依赖注入,就是依赖抽象而不依赖于具体的实现。理解起来有点抽象。先来看看这段代码:

public interface Itingting {
    /**
     * 婷婷会做饭的方法,
     * 具体做的什么菜以抽象的方式声明
     * 吃的时候进行实例化即可
     * 这样做的好处就是一个方法可以声明出婷婷会做好多菜
     * 想吃什么菜就将那个菜进行实例化即可
     * @param food
     */
    public void cook(Food food);
}
public class TingTing implements Itingting {
    //婷婷实现做饭的接口
    @Override
    public void cook(Food food) {
        // TODO Auto-generated method stub
        food.eat();
    }
}
/**
 * 
 * @author婷婷
 * 食物类接口
 * 定义了一个eat方法
 *
 */
public interface Food {
    public void eat();
}
/**
 * 
 * @author婷婷
 * 食物类接口
 * 定义了一个eat方法
 *
 */
public interface Food {
    public void eat();
}
//做白菜
public class Cabbage implements Food{
    @Override
    public void eat() {
        // TODO Auto-generated method stub
        System.out.println("婷婷做的白菜也不错!!!");
    }

}
/**
 * @author 婷婷
 * 描述婷婷在家吃饭的场景
 */
public class Home {
    public static void main(String[] args) {
        //创建出婷婷对象
        Itingting tingting = new TingTing();
        //调用婷婷做鱼
        Food fish = new Fish();
        //调用婷婷做白菜
        Food cabbage = new Cabbage();
        //做好了就开始吃
        tingting.cook(fish);
        tingting.cook(cabbage);
    }
}

上述代码就是一个符合依赖注入原则的Demo,结合上述代码来解释不难发现,其实该原则有以下三点说明:
1、高层模块不应该依赖于底层模块,两者多应该依赖于抽象,
2、抽象不应该依赖于细节,即具体实现类。
3、细节应该依赖于抽象。
听起来起来有点乱,看上述的代码吧,上述代码中将婷婷做饭的方法用抽象的形式描述,即说明婷婷会做各种菜,而不是单纯的只会做某一种菜,当你需要吃什么菜的时候
你就可以实现该接口(抽象)即可。这样做的话就可以实现各个类或者模块之间的相互独立,彼此之间互不影响。实现了模块之间的松耦合。
依赖注入原则有如下的三种方式实现:
1、通过构造函数传递依赖对象
2、通过setter来传递依赖对象
3、通过接口声明实现依赖对象
上述代码中就是通过通过接口声明实现依赖对象。好了,再来聊聊下一个设计原则吧。
接口分离原则:该原则的核心思想就是不强迫客户程序依赖他们不需要的方法。简而言之就是一个接口不需要提供太多的行为,一个接口应该只提供一种对外实现的功能,避免造成接口污染。
这个原则其实很好理解,我们都知道,实现一个接口的时候我们必须要实现该接口的所有的抽象方法,而该接口中如果出现了我们并不需要的方法时就会造成接口污染。
而接口分离原则就很好的解决了该问题。
接着就是第五个原则了,迪米特原则:该原则主要核心思想就是一个对象应该对其他对象经可能少的了解,也就是说降低各对象之间的耦合。其是我们在了解了前面集中原则之后应该不难理解这个。说白了。该原则就是为了类之间的解耦,只有类和类之间的耦合性比较低的时候才能够更好的进行复用。
接着来看开闭原则:开闭原则也是比较简单,该原则的核心思想主要就是对一个类的改动是通过增加代码进行的,而不能改动原来的代码。即一个对象对扩展开放,对修改关闭。
聊到了这里你们有没有发现前面的5种设计原则其实就是为了实现开闭原则!!!
没错!其实前面的几种原则就是为了实现对扩展开放,对修改关闭的终极目标!
好了,相信大家已经了解到了架构中的这几大设计原则了吧
哦!对了。还有合成复用原则。其实这个原则主要也是为了降低类和类之间的关系,即优先使用组合而不是继承。
好了,关于架构中的设计原则就先给大家介绍到这里了。
后续的文章将运用这些设计原则给大家介绍Java web相关的知识。

猜你喜欢

转载自blog.csdn.net/qq_38701478/article/details/80303631