JAVA设计原则之依赖倒置原则

Whatjava

  Dependence Inversion Principle(DIP):高层模块不该该依赖底层模块,都应该依赖于抽象;抽象不该该依赖于具体,具体依赖于抽象this

  Why设计

  若高层依赖于底层,那么底层的变更也会致使高层的变更,这就会致使模块的复用性下降并且大大提升了开发的成本。如果依赖于抽象的话,那么是比较稳定的,底层或者高层的变更都不会互相影响。code

  How对象

  不少地方引用的我的以为也很是有表明性的一个例子:公司是福特和本田公司的金牌合做伙伴,现要求开发一套自动驾驶系统,只要汽车上安装该系统就能够实现无人驾驶,该系统能够在福特和本田车上使用,只要这两个品牌的汽车使用该系统就能实现自动驾驶。继承

  福特汽车类,包含三个方法,启动、中止、转弯接口

class FordCar
    {
        public void Run()
        {
            Console.WriteLine("FordCar run");
        }

        public void Stop()
        {
            Console.WriteLine("FordCar stop");
        }

        public void Turn()
        {
            Console.WriteLine("FordCar turn");
        }
    }

宏达汽车类,包含三个方法,启动、中止、转弯ip

class HondaCar
    {
        public void Run()
        {
            Console.WriteLine("HondaCar run");
        }

        public void Stop()
        {
            Console.WriteLine("HondaCar stop");
        }

        public void Turn()
        {
            Console.WriteLine("HondaCar turn");
        }
    }

自动驾驶系统,有三个方法启动汽车、中止汽车、汽车转向ci

class AutoSystem
    {
        HondaCar hondaCar = new HondaCar();
        FordCar fordCar = new FordCar();
        CarType type;

        public AutoSystem(CarType type)
        {
            this.type = type;
        }

        public void RunCar()
        {
            if (type == CarType.Honda)
            {
                hondaCar.Run();
            }
            else if (type == CarType.Ford)
            {
                fordCar.Run();
            }
        }

        public void StopCar()
        {
            if (type == CarType.Honda)
            {
                hondaCar.Stop();
            }
            else if (type == CarType.Ford)
            {
                fordCar.Stop();
            }
        }

        public void TurnCar()
        {
            if (type == CarType.Honda)
            {
                hondaCar.Turn();
            }
            else if (type == CarType.Ford)
            {
                fordCar.Turn();
            }
        }
    }

目前来看,是知足需求的,可是随着发展业务也在发展,如今若是发展了伙伴,须要对其余品牌的汽车添加自动驾驶系统,好比红旗、奇瑞等品牌,那么若是沿用之前的方式,就须要去修改AutoSystem了,先增长两个新的品牌汽车的对象,而后在启动汽车、中止汽车、汽车转向中进行修改增长分支语句对不一样的品牌来进行判断而后加上各类操做,这样就违背的OCP,并且复杂的分支语句也会容易形成错误,若是之后再继续扩展其余的品牌的话,那么这样的程序确定是不易于维护的,程序的健壮性是较差的,大大的增长了开发的成本。那么敏感的同窗已经看出来,既然不一样的汽车品牌之间都拥有相同的行为,那么为何不定义一个接口呢?如今咱们先来定义一个接口,而后将各个品牌的汽车实现这个接口实现,那么在AutoSystem中咱们就能够针对定义的接口操做了。开发

interface ICar
    {
        void Run();
        void Stop();
        void Turn();
    }

自动驾驶系统也就是高层模块如今针对的是这个抽象的接口,不管什么汽车,只要实现了ICar接口,就能进行相关的操做。

class AutoSystem
    {
        ICar car;

        public AutoSystem(ICar car)
        {
            this.car = car;
        }

        public void RunCar()
        {
            car.Run();
        }

        public void StopCar()
        {
            car.Stop();
        }

        public void TurnCar()
        {
            car.Turn();
        }
    }

福特汽车类也就是底层模块,实现了ICar接口,如今依赖的是抽象的接口

class FordCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("FordCar run");
        }

        public void Stop()
        {
            Console.WriteLine("FordCar stop");
        }

        public void Turn()
        {
            Console.WriteLine("FordCar turn");
        }
    }

宏达汽车类也就是底层模块,实现了ICar接口,如今依赖的是抽象的接口

class HondaCar : ICar
    {
        public void Run()
        {
            Console.WriteLine("HondaCar run");
        }

        public void Stop()
        {
            Console.WriteLine("HondaCar stop");
        }

        public void Turn()
        {
            Console.WriteLine("HondaCar turn");
        }
    }

 当高层模块依赖底层的时候,那么高层的复用性就较差,就如上例所说的增长汽车品牌种类。若是高层与底层都是依赖于抽象的话,那么高层复用性就较好,由于经过继承象出来的接口实现多态,那么复用的地方就多了,这样的设计无疑是较为稳定的。

相关文章
相关标签/搜索