zoukankan      html  css  js  c++  java
  • 对设计原则【依赖倒置】的一些理解

    作为一名oop程序员,设计原则是必须知道的知识:单一职责,开闭原则,依赖倒置,接口隔离,替换法则。

    在看【Head First】一书时,突然对依赖倒置有了一些简单的理解。

      先看依赖倒置的定义:要依赖抽象,不要依赖具体类。

        其意思是具体类要依赖抽象,抽象不应该依赖具体类,更扩展一点就是说具体类也尽量不要依赖具体类。

      首先,何为具体类,我的理解,具体类应该就是某个具体的对象,是对现实中的实物或其他的一种反应,即就是类的实例,具体代码上就是通过new出来的对象。

    比如Object obj  = new Object();这样便产生了一个具体对象。而若是直接在一个对象中new另一个对象,则这两个对象依赖在了一起,增加了这个类的耦合性。

      让我们先回到依赖倒置上!这个倒是有点像面向接口编程,但是这里更强调的“抽象”,这种抽象可以是一个接口,也可以是一个抽象类。这个原则说明了:不能让

    “高层组件”依赖“低层组件”,而且两者都应该依赖于抽象。

      我来举一个例子。如果我们要开一家奶茶店,那我们首先想到的是什么呢,肯定是想到在什么地方开奶茶店,要多少员工,然后才是卖什么奶茶。

      没错,我们的思考方法一般都是从顶端 开始,然后往下才是具体类。但是要开奶茶店又要想怎么生产奶茶,这是一件很要命的事情。对于一个奶茶店主来说,并不

    想理会奶茶这写具体类,否则奶茶店将全部依赖这些奶茶具体类。这时候就要倒置我们的思想,先从低端开始,从奶茶开始,抽象出一个奶茶抽象。

      这时候“奶茶店”就是“高层组件”,各种奶茶就是“低层组件”。由于奶茶店是如果买奶茶的具体类,则奶茶店对全部奶茶有了依赖,高层组件与低层有了依赖关系。

      这个模式告诉我们:我们应该依赖抽象类,而不应该具体类,无论是高层组件还是低层组件都应该如此。

      那么我们就想到定义一个奶茶的抽象类型,即为所有的奶茶提供一个抽象,而奶茶店则只需要面对这个抽象,而不用去管这个抽象的具体类是什么。即奶茶店只需

    要专注于卖奶茶,收钱找钱什么的,而不用管具体奶茶是什么。这样奶茶店就依赖于奶茶的抽象,而不是依赖奶茶的具体类。

      

    class TeaShop{
    
        public void sell(){
             
              Tea tea = new SimpleTea();
               
               tea.produce();
       }
    
    }

              这样虽然我们创建了一个抽象,但我们 仍在代码中,实际的创建的具体类(SimpleTea),所以,这样的抽象并不能实现低耦合。

      这时候,可以使用工厂模式来对代码进行进一步重构,来创建一个TeaFactory;为了使这个工厂更具有扩展型,我们来对工厂进行抽象。

    public class abstract TeaFactory{
      
         public Tea makeTea(String type){
            createTea(type).produce();
         }
    
        public abstract Tea  createTea(String tea);
    
    }

      这时候我们在郑州开了个奶茶店,则创建一个郑州奶茶工厂。

    public class ZZTeaFactory extends TeaFacory{
    
       public Tea createTea(String tea){
            if(tea.equles("simple")){
                 return new SimpleTea();
          }else{
                   return new OtherTea();  
           }
     }
     
    } 

      这样就实现了一个奶茶的工厂模式。那么通过奶茶店进行点选奶茶的时候:

      

    class TeaShop{
    
        public void sell(){
             TeaFactory factory = new ZZTeaFactory();
              Tea tea = factory.makeTea("simple");
               
       }
    
    }

      我们通过工厂模式将奶茶店与奶茶进行解耦,而且通过工厂模式也大大提高了程序的可扩展型,比如我们如果要在洛阳也开一家奶茶店的话,但是洛阳奶茶店所卖的

    奶茶与郑州的奶茶并不一样,这时候我们只要实现一个洛阳的奶茶工厂,实现奶茶工厂的抽象即可,实现了开闭原则。通过这种将实例化延迟到子类中进行的方式。

      在次回到依赖倒置上,为什么使用工厂模式就实现了依赖倒置了呢?

      首先我们画一下类图:

        

                 这时候高层组件(TeaShop)和低层组件(SimpleTea,OtherTea)都依赖于Tea抽象。想要遵循依赖倒置原则,工厂方法并非是唯一的方法,但却是

    最有效的方法。

      

      如何避免违反依赖倒置原则:

        1.变量不可以持有具体类的引用。(持有类的引用即通过new出来的对象)

        2.不要让类派生自具体类。(如果派生自具体类,就产生了依赖,请派生自一个抽象)

        3.不要覆盖基类中已实现的方法。

      但是如果随时都要遵循这个原则,是不可能的,因为我们如果不new一个对象,那么我们是什么都写不成的。所以这个原则也有适用行。如果有一个不像是会改变

     的类,则具体类一点问题都没有的。而常改变的 类则可以使用一些技巧。

      永远不变的是变化本身,我们使用设计原则,设计模式,则是为了更好的应对变化,封装变化。

      参考资料:《Head First 设计模式》

  • 相关阅读:
    ElasticSearch聚合分析API——非常详细,如果要全面了解的话,最好看这个
    wiredtiger引擎性能——比levelDB更牛叉!
    mongodb数据文件结构——record是内嵌BSON的双向链表,多个record或索引组成extent
    MongoDB Wiredtiger存储引擎实现原理——Copy on write的方式管理修改操作,Btree cache
    elasticsearch聚合操作——本质就是针对搜索后的结果使用桶bucket(允许嵌套)进行group by,统计下分组结果,包括min/max/avg
    splunk的统计分析功能——特定字段的统计功能包括取值分布(+topK,min/max/平均值)
    在SQLAlter在现场一定的价值
    Android4.0设置接口变更摘要(四)
    Nagios监控生产环境redis群集服务战
    Facebook Asynchronous Layout and Rending
  • 原文地址:https://www.cnblogs.com/lic309/p/4107260.html
Copyright © 2011-2022 走看看