依赖注入(Dependency Injection)

依赖注入是面向对象开发中对象间解耦合的一种策略,它也可称为控制反转(Inversion of Control)或者依赖倒置原则(Dependence Inversion Principle)。

这个概念说白了就是:我只做我关注的事情,其他不确定的事情你们其他人去实现吧。

控制反转,反转的是什么,反转的是对程序的控制权。程序组件为调用者提供服务的同时,还需要能让调用者定制一些功能,只要符合组件的接口,调用者就可以将定制的功能设置给组件,这就相当于将控制权转交给了调用者,这样组件不会依赖于一些可变的功能,对于调用者来说使用组件也可以更加灵活更加可扩展。

正如依赖倒置原则说的要依赖于抽象,不要依赖于具体,要对抽象进行编程。作为一个功能或者组件的开发者来说,要尽量将自己的一些具有可变性的依赖进行抽象。

下面来遐想一个场景举例说明:

class MediaPlayer {
    private FileLogger logger = new FileLogger(@"c:\log.txt");
    public void Play(string filePath) {
        try {
            // do play ...
            logger.log("正在播放");
        } catch {
            logger.error("播放失败");
        }
    }
}

上边的代码意图去实现一个媒体播放功能的组件,为了记录播放状态MediaPlayer依赖于FileLogger,使用者角度来说只能通过c:\log.txt查看播放状态,并无权更改。如果需要通过Trace或者Console方式输出播放状态,组件开发者就需要修改代码。这时就需要依赖注入,实现方式可以分为三种:

1. 构造注入

class MediaPlayer {
    private Logger logger;
    public MediaPlayer(Logger logger) {
        this.logger = logger;
    }
    public void Play() {
        try {
            // do play ...
            logger.log("正在播放");
        } catch {
            logger.error("播放失败");
        }
    }
}

// 调用
new MediaPlayer(new FileLogger(@"c:\log.txt")).Play();
new MediaPlayer(new TraceLogger()).Play();
new MediaPlayer(new ConsoleLogger()).Play();

2. 赋值注入

class MediaPlayer {
    private Logger logger;
    public void SetLogger(Logger logger) {
        this.logger = logger;
    }
    public void Play() {
        try {
            // do play ...
            logger.log("正在播放");
        } catch {
            logger.error("播放失败");
        }
    }
}

// 调用
MediaPlayer player = new MediaPlayer();
player.SetLogger(new ConsoleLogger());
player.Play();

3. 接口注入

interface ILoggerProvider {
    void AddLogger(Logger logger);
}

class MediaPlayer : ILoggerProvider {
    private Logger logger;
    public void AddLogger(Logger logger) {
        this.logger = logger;
    }
    public void Play() {
        try {
            // do play ...
            logger.log("正在播放");
        } catch {
            logger.error("播放失败");
        }
    }
}

// 调用
MediaPlayer player = new MediaPlayer();
player.AddLogger(new ConsoleLogger());
player.Play();

通过依赖注入方式,MediaPlayer将Logger进行了抽象,依赖于一个抽象的Logger,将Logger的实现丢给了调用者,调用者可以通过硬编码或者通过XML配置文件方式来创建不同的Logger,然后注入到MediaPlayer中。

 

posted @ 2013-04-16 15:22  CanMusic  阅读(395)  评论(0编辑  收藏  举报