OOP系列之聊聊依赖

栏目: 后端 · 发布时间: 6年前

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

依赖,或者用英语更准确,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();
}

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


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web标准设计

Web标准设计

刘杰(嗷嗷) / 清华大学出版社 / 2009-1 / 75.00元

一扇经常开启的门的铰链不需要润滑油。 一条湍急的河流不会变得污浊。 无论是声音还是想法都不可能在真空中传播。 Web标准如果不用就会腐朽。 这世界真奇妙! 专题页面:http://www.aoao.org.cn/book/web-standards-design/一起来看看 《Web标准设计》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具