OOP系列之聊聊依赖

依赖,或者用英语更准确,dependency,是程序设计中不同对象或方法之间所必不可少的,我们的代码就是由不同的方法不同的对象相互调用组成的,因此,对于依赖,我们要做到心里有数,依赖是如何产生的,依赖的强弱关系是怎样的。依赖的强弱是指依赖者对被依赖对象的依赖程度,即替换被依赖对象所花费的代价程度如何,依赖程度越强,替换掉被依赖对象的代价就越大,方法越底层,难度越大,灵活性越差。
下面是我总结出来的引入依赖的几种形式,由强到弱依次排列

1.继承产生的依赖

SubClass对父类BaseClass的依赖是绝对的,编译时即确定的,这种依赖无法被替换,不能在运行时让SubClass继承另外一个父类

public class SubClass : BaseClass
{}

解决办法:由于这种继承关系在代码写下的那一刻已经确定,因此无法通过任何方法来替换这种继承关系,因此建议在程序设计时,首先考虑继承关系是否有必要,能否用组合关系代替继承关系。如果要override父类的方法,则必须继承,如果只用到父类的某些方法,建议用组合替代继承

2.由new关键字创建对象产生的依赖

下面的例子中,通过new关键字引入了对Car类的依赖,这种依赖也是无法被替换的,并且这种依赖的形式较为隐蔽,无法通过看类的定义或者方法签名直接看出来,需要避免。

public void RunACar()
{
    Car a = new Car();
    a.Run();
}

or

private Car aCar = new Car();

解决办法:尽量不要在方法体或者类内部用new关键字生成对象,应该通过方法参数或者依赖注入或者构造注入来处理这种依赖。

方法参数:
public void RunACar(Car car)
{
    a.Run();
}

依赖注入:
public class A 
{
    [Dependency]
    private Car aCar;
    public void RunACar()
    {
        a.Run();
    }
}

构造注入:
public class A
{
    private Car aCar;

    public A(Car car)
    {
        this.aCar = car;
    }

    public void RunACar()
    {
        aCar.Run();
    }
}    

3.静态方法

静态方法也是一种在编译时已经确定的依赖,无法被替换。

public class Car
{
    public static void Run() {}
}

public void RunACar()
{
    Car.Run()
}

解决办法:
静态方法应该设计为无状态的,无论调用者是谁,只要输入一致,输出的结果应该是相同的。如果是有状态的,考虑把静态方法设计为实例方法,并参照第二条由new关键字产生的依赖的解决方法。

4.类数据成员的类型

下面的例子中AService类对Car类的依赖,Car类是数据成员carList的类型,这种依赖是可以在运行时通过构造注入或依赖注入用Car类的子类型替换Car。

public class AService : IAService
{
    private Car aCar;
}

运行时替换:

假设有个子类Track继承了Car类

public class Track: Car {}

依赖注入替换:
public class AService : IAService
{
    [Dependency(typeof(Track))]
    private Car aCar;
}

构造注入替换:
public class AService : IAService
{
    private Car aCar;
    public AService(Car car)
    {
        aCar = car;
    }
}

var car = new Track();
var service = new AService(car);

5.方法参数引入的依赖(构造方法或成员方法)

这种方式提供了更大的灵活性,可以在运行时动态替换Car的类型

public void RunACar(Car car)
{
    a.Run();
}

我们应该尽量选择依赖程度较小的方式来实现代码,以换取更大的灵活性,在日常写代码的时候多注意这些细节,才能更加精进自己的编程能力和技巧。今天就到这吧。

打赏

猜你喜欢

博主开通了微信公众号,欢迎关注啦

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.