美文网首页
第五条:优先考虑依赖注入来引入资源

第五条:优先考虑依赖注入来引入资源

作者: taogan | 来源:发表于2020-12-01 20:30 被阅读0次

有许多类会依赖一个或者多个底层的资源,例如:拼写检查器需要依赖词典。因此,像下面这种把类实现为静态工具类的做法很常见。

public class SpellChecker{
   private static final Lexicon dictionary = ...;

   private SpellChecker(){
   }

   public static boolean isValid(String word){
   }

   public static List<String> suggestions(String typo){
   }
}

同样的,将这些类实现为Singleton的做法也并不少见

public class SpellChecker{
   private static final Lexicon dictionary = ...;

   private SpellChecker(){
   }
   
   public static final INSTANCE = new SpellChecker();
   
   public static boolean isValid(String word){
   }

   public static List<String> suggestions(String typo){
   }
}

以上两种方式都不理想,因为它们都假定为只有一本词典,实际上,每种语言都有自己不同的词典,特殊语言还有特殊的词典等等。因此假定用一本词典来满足所有需求,是不现实的。所以静态工厂和Singleton不适合用于需要引用底层资源的类。

这里需要的是能支持类的多个实例,每一个实例都使用客户端指定资源。满足需求最简单的模式是:当创建一个新的实例时,就将资源传入到构造器,这就是依赖注入的一种形式:词典是拼音检查器的一个依赖,在创建拼音检查器时就将词典注入到其中。

public class SpellChecker{
   private final Lexicon dictionary;

   public SpellChecker(Lexicon dictionary){
       this.dictionary = dictionary;
   }
       
   public boolean isValid(String word){
   }

   public List<String> suggestions(String typo){
   }
}

这种模式的另一个变体是,将资源工厂传给构造器,工厂是可以被重复调用来创建类的实例的一个对象,在Java8中增加的接口Supplier<T>,最适合用于表示工厂,带有Supplier<T>的方法,通常应该限制输入工厂的类型参数,使用有限制的通配符类型,以便来创建指定限定类型的任意子类型:例如

public class DependencyInjection {

    public static void main(String[] args) {
        SpellChecker spellChecker = new SpellChecker(ChineseLexicon::new);
    }

}

class SpellChecker {
    private final Lexicon dictionary;

//    public SpellChecker(Lexicon dictionary){
//        this.dictionary = dictionary;
//    }

    public SpellChecker(Supplier<? extends Lexicon> dictionary) {
        this.dictionary = dictionary.get();
    }

}

interface Lexicon {

}

class ChineseLexicon implements Lexicon {

}
public class DependencyInjection {
    public static void main(String[] args) {
        SpellChecker spellChecker = new SpellChecker(ChineseLexicon::new);
    }
}

虽然依赖注入极大的提升了灵活性和可测试性,但是如果使用过度,会导致凌乱不堪,因为可能包含上千个依赖,不过这种凌乱,用一个依赖注入框架就可以终结,如Spring,Dagger,Guice等。但是设计成手动依赖注入的API,一般都适用于这些框架。

总而言之,不要用Singleton和静态工具类来实现依赖注入一个或者多个底层资源,且该资源的行为会影响到该类的行为,也不要直接用这个类来创建资源,而是将这些资源或者工厂传递给构造器,通过它来创建资源类,这种实践被称为依赖注入,它极大的提高了类的灵活性、可重用性何可测试性。

相关文章

  • 提示五

    今天看第五条:优先考虑依赖注入来引用资源。 依赖注入(Dependence Inversion)指在创建新实例时将...

  • 第五条:优先考虑依赖注入来引入资源

    有许多类会依赖一个或者多个底层的资源,例如:拼写检查器需要依赖词典。因此,像下面这种把类实现为静态工具类的做法很常...

  • 1.5优先考虑依赖注入来引入资源

    1.5优先考虑依赖注入来引入资源 1.5.1 ​ 静态工具类和Singleton类不适合于需要引用底层资...

  • Java之优先使用依赖注入

    《Effective Java》的第五条,提到了优先使用依赖注入的观点。刚好最近在学Spring,就顺便来谈谈我的...

  • spring

    依赖注入通常有如下两种:设置注入和构造注入: 构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入 设...

  • 依赖查找和依赖注入

    依赖查找和依赖注入的区别 依赖查找:容器中的对象通过Api来查找自己所依赖的资源和对象 依赖注入:依赖对象和注入对...

  • 面试官:你给我讲一下什么是spring依赖注入?网友:就这啊,太

    什么是依赖注入 依赖 : 指Bean对象的创建依赖于容器 . 注入 : 指Bean对象所依赖的资源 , 由容器来设...

  • Dagger2基本使用

    Dagger2是一个依赖注入框架,目前由google维护。关于依赖注入是什么可以看依赖注入简介 引入Dagger ...

  • 依赖注入的方式

    依赖注入: 依赖于某些方式给Bean的资源进行注入 Spring 支持三种依赖注入的方式 属性注入 构造器注入 工...

  • SpringBoot 单元测试

    SpringBoot 单元测试 依赖注入 引入依赖: 这里引入了一个spring-boot-starter-tes...

网友评论

      本文标题:第五条:优先考虑依赖注入来引入资源

      本文链接:https://www.haomeiwen.com/subject/umhkwktx.html