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();
}

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


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

查看所有标签

猜你喜欢:

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

High Performance Python

High Performance Python

Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99

If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!

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

在线压缩/解压 HTML 代码

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具