依赖倒转原则

1.定义

          依赖倒转原则(Dependence Inversion Principle ,DIP)定义为:高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖细节,细节应该依赖于抽象。简单的就是说,要针对接口或者抽象类编程,而不是针对具体类编程,感觉和开闭原则等都极为相似。

2.实例

          某系统提供一个数据转换模块,可以将来自不同数据源的数据转换成多种格式(为了简单实现效果,不做实际转换,只让结果简单打印,如可以转换来自数据库的数据(DatabaseSource),也可以转换来自文本文件的数据(TextSource),转换后的格式可以是XML文件(XMLTransformer),也可以是XLS文件(XLSTransformer)等。初始设计图如下:

          

3.分析

          由于需求的变化,该系统可能需要增加新的数据源或者新的文件格式,每增加一个新的类型数据源或者新的文件格式,客户类MainClass就会修改源代码,违背了开闭原则。现在使用依赖倒转原则进行重构,结果如下图:

          

          本实例中,MainClass针对具体类编程,如果增加新类就必须修改MainClass中的源代码,因此可以对这些具体类进行抽象化,使得MainClass针对抽象类编程,而将具体的类放在配置文件中,重构后添加了AbstractSource和AbstractTransformer,在这个过程中使用了里氏代换原则,依赖倒转原则必须以里氏代换原则为基础,当需要增加新的转换源或者文件时就只需要添加新的类和修改xml配置文件即可。

4.实现

          4.1XMLHelper,这个类在前面也出现过,主要作用就是读取xml文件中具体类名,这里不再过多叙述。    

package DependenceInversion;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XMLHepler {

    /*
     * 从xml文件读取类名
     * 
     * */
    public XMLHepler() {
         
    }
    public String  getSourceTransferClassName()
    {
        
        DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
        DocumentBuilder builder=null;
        try {
            builder=factory.newDocumentBuilder();
        }catch(ParserConfigurationException e)
        {
            e.printStackTrace();
        }
        Document document=null;
        try {
            document=builder.parse("DIP.xml");//从xml文件读取类名
        }catch(SAXException e)
        {
            e.printStackTrace();
        }catch(IOException e)
        {
            e.printStackTrace();
        }
        NodeList nList1=document.getElementsByTagName("sourceName");
        NodeList nList2=document.getElementsByTagName("transformerName");
         
        String reString=  nList1.item(0).getFirstChild().getNodeValue()+" "+ nList2.item(0).getFirstChild().getNodeValue();
        return reString;
    }
}

          4.2AbstractSource类     

package DependenceInversion;
public abstract class AbstractSource {

    public AbstractSource() { 
    } 
    public abstract String getData();//此处为了方便 并不去实现数据转换 只是为了体现效果

}

          4.3AbstractTransformer类 

package DependenceInversion;
public abstract class AbstractTransformer {

    public AbstractTransformer() {
        // TODO Auto-generated constructor stub
    }
    public abstract void transformerData(AbstractSource source);
    
}

          4.4DatabaseSource类     

package DependenceInversion;
public class DatabaseSource extends AbstractSource{
    public DatabaseSource() {         
    }
     @Override
    public  String getData()
    {
          return "DatabaseSource";
    }
}

          4.5TextSource类   

package DependenceInversion;
public class TextSource extends AbstractSource{
    public TextSource() {
         
    }
    @Override
    public String getData()
    {
        return "TextSource";
    }
}

          4.6XLSTransformer类   

package DependenceInversion;
public class XLSTransformer extends AbstractTransformer {
    public XLSTransformer() {         
    }
    @Override
        public   void transformerData(AbstractSource source) 
        {
            System.out.println("XLSTransformer转换了->"+source.getData());
        }
}

          4.7XMLTransformer类   

package DependenceInversion;
public class XMLTransformer extends AbstractTransformer{
    public XMLTransformer() {     
    }
    @Override
    public   void transformerData(AbstractSource source)
    {
        System.out.println("XMLTransformer转换了->"+source.getData());
    }
}

          4.8MainClass类      

package DependenceInversion;
public class MainClass {
    private AbstractSource source=null;
    private AbstractTransformer transformer=null;
    private XMLHepler hepler=null;
    public MainClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
         hepler=new XMLHepler();
         String classNames=hepler.getSourceTransferClassName();
         String[]res= classNames.split(" ");//从返回的类名中分别找到sourceName和transformerName
          source=(AbstractSource)Class.forName(res[0]).newInstance() ;
         transformer=(AbstractTransformer)Class.forName(res[1]).newInstance();
         transformer.transformerData(source);
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
         
       new MainClass();
    }

}

          4.9运行效果

           

            

      注:参考书籍是清华大学出版社《设计模式》,由刘伟主编,代码中存在的不足还请多多指教。
原文地址:https://www.cnblogs.com/Juice-Dreamer/p/9866613.html