依赖倒转原则
Posted juice-dreamer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了依赖倒转原则相关的知识,希望对你有一定的参考价值。
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运行效果
注:参考书籍是清华大学出版社《设计模式》,由刘伟主编,代码中存在的不足还请多多指教。
以上是关于依赖倒转原则的主要内容,如果未能解决你的问题,请参考以下文章