Effective Java3.5-优先考虑依赖注入来引用资源

5 优先考虑依赖注入来引用资源

主要内容:讲述在使用静态工具类,Singleton类时,最好不要依赖于其他的底层资源类,意味着静态工具类和Singleton最好是独立的类,即使需要用到其他的参数,也最好不要引用其他对象,更不要是一个类的同种变形(比如它的子类们或者组合类)

主要目标:使用静态工具类,Singleton类时不引用特定的(底层)资源。创建实例时就将资源(另一个对象)传到构造器。使用Supplier来控制资源(另一个对象)的类型(上界)。使用资源工厂来获得资源,并将工厂作为“另一个对象”作为传到构造器的参数。

实际应用场景:Spring的依赖注入。

Effective Java知识点摘录+白话说明

  1. 静态工具类和 Singleton 类不适合需要引用底层资源的类

    意思是如果一个类,它需要根据不同的对象属性创建不同的实例,最好不要变成静态类或者Singleton类。比如拼写检查器SpellChecker需要根据不同的字典Dictionary来创建对象,比如传入EnglishDictionary或者ChineseDictionary,此时的SpellChecker最好不要是静态类或者Singleton类。试想一下,静态类和Singleton在JVM生成时都只有一个并且只能有一个,总不能二选一吧?

  2. 这里需要的是能够支持类的多个实例(在本例中是指 SpellChecker ),每一个实例都使用客户端指定的资源(在本例中是指字典)。满足该需求的最简单的模式是, 当创建一个新的实例时,就将该资源传到构造器中。

    意味着在创建多个需要资源(另外一个类的实例,如Dictionary)的类(如SpellChecker)时,可以在这个类的构造器中放入这个参数,作为这个类的属性。需要注意的是,当采用这种方法来创建实例时,需要将资源添加上final。

    这就是依赖注入。

    //在构造器方法中使用了dictionary参数
    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){}
    }
    
  3. 这个程序模式的另一种有用的变体是,将资源工厂( factory )传给构造器。工厂是可以被重复调用来创建类型实例的一个对象。这类工厂具体表现为工厂方法。Java 8中增加的接口 Supplier <巴,最适合用于表示工厂。带Supplier<T>通常应该限制输入工厂的类型参数使用有限制的通配符类型 ( bounded wildcard type ),以便客户端能够传入一个工厂,来创建指定类型的任意子类型。

    这意味着不一定要将Dictionary作为属性传入,可以将生成Dictionary的工厂作为参数引入。这里可以考虑使用java8新特性-Supplier<T>或者Suppiler<? extends SomeObject>。这里就可以设置好引入的类型限制,并可以尝试使用Java8 的lambda表达式来顺便创建引入对象。(当然你也可以不用,而是选择用简单的new)

    public class DependencyInjection {
        public static void main(String[] args) {
            SpellChecker spellChecker = new SpellChecker(ChineseLexicon::new);
            //SpellChecker spellChecker = new SpellChecker(new ChineseLexicon());
        }
    
    }
    
    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 {
    
    }
    
  4. 总而言之,不要用 Singleton 和静态工具类来实现依赖一个或多个底层资源的类,且该资源的行为会影响到该类的行为 ;也不要直接用这个类来创建这些资源,而应该将这些资源或者工厂传给构造器(或者静态工厂,或者构建器),通过它们来创建类这个实践就被称作依赖注入,它极大地提升了类的灵活性 可重用性和可测试性。

    这不就是静态类,singleton类,构造器与依赖注入的比较之一吗?

个人总结

Q:暂无嘿嘿

A:那肯定也没有的啦

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值