zoukankan      html  css  js  c++  java
  • 依赖倒转原则

    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运行效果

               

                

          注:参考书籍是清华大学出版社《设计模式》,由刘伟主编,代码中存在的不足还请多多指教。
  • 相关阅读:
    TCP 连接断连问题剖析
    libtool: link: you must specify an output file
    socket编程bind浮动ip
    epoll或者kqueue的原理是什么?
    推荐 30 款最好的免费项目管理软件
    QNX开发最完整图文教程(官方文档,非官方翻译)
    Android 4.X系列の界面设计中退出Android程序的代码
    APScheduler 定时任务系统
    给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。
    APSchenuler嵌入Django
  • 原文地址:https://www.cnblogs.com/Juice-Dreamer/p/9866613.html
Copyright © 2011-2022 走看看