Chinaunix首页 | 论坛 | 博客
  • 博客访问: 270357
  • 博文数量: 88
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 840
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-20 21:13
文章分类

全部博文(88)

文章存档

2022年(1)

2017年(1)

2016年(2)

2015年(1)

2014年(83)

分类: Java

2014-05-07 11:08:32

依赖和耦合(dependency and coupling)
  Rose中定义“依赖”:依赖描述了两个模型元素之间的关系。如果被依赖的模型元素发生变化就会影响到另一个模型元素。
  Martin Fowler描述“耦合”:如果改变程序的一个模块要求另一个模块同时发生变化,就认为这两个模块发生了耦合。
  可看出:如果模块A调用模块B提供的方法,或者访问模块B中的某些数据成员(在OO中是不提倡这样做的),我们就认为模块A依赖于模块B,模块A和模块B之间发生了耦合。
  究竟需不需要耦合?
  如果所有模块之间都没有任何耦合关系,其结果必然是:整个软件不过是多个互不相干的系统的简单堆积,对这个系统而言,所有功能还是要做一个模块中实现,这等于是没有做任何模块的分解。
  所以,永远不要幻想消除所有的依赖。要控制和消除不必要的耦合.
  
  接口和实现分离(separation of interface and implementation )
  特点:
  1.应用程序调用类库,依赖于类库
  2.接口和实现的分离从一定的程度上消解了这个依赖关系,具体的实现可以在编译期间发生变化,但是,这种消解方法的作用非常有限.
  3.类库可以单独重用,但是应用程序不能脱离类库而重用,除非提供了一个实现了相同接口的类库。  

点击(此处)折叠或打开

  1. //example
  2. //this is the library code
  3. public abstract class Reader {
  4.     public abstract int read();
  5. }
  6. public abstract class Writer {
  7.     public abstract void write();
  8. }
  9. public class KeyboardReader extends Reader{
  10.     public int read(){
  11.         int n=0;
  12.         //read code
  13.         return n;
  14.     }
  15. }
  16. public class PrintWriter extends Writer{
  17.     public void write(){
  18.         //doing something...
  19.     }
  20. }
  21. //this is the application code
  22. public class Application {
  23.     public KeyboardReader reader;
  24.     public PrintWriter writer;
  25.     public void copy(){
  26.         int c=0;
  27.         while(c!=reader.read())
  28.             writer.write();
  29.     }
  30. }
  依赖倒置(dependency inversion principle)
  A.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象
  B.抽象不能依赖于具体,具体依赖于抽象
  含义:为了消解两个模块之间的依赖关系,应该在两个模块之间定义一个抽象接口,上层模块调用定义的函数,下层模块实现该接口。
  特点:
  1.应用程序调用类库的抽象接口,依赖于类库的抽象接口;具体的实现类派生自类库的抽象接口,也依赖于类库的抽象接口
  2.应用程序和具体的类库实现完全独立,相互之间没有直接的依赖关系。只要保持接口类的稳定,应用程序和类库的具体实现都可以独立的发生变化
  3.类库完全可以独立重用,应用程序和任何一个实现了相同抽象接口的类库协同工作。  

点击(此处)折叠或打开

  1. //example
  2. // keep the classes: Reader, Writer, KeyboardReader, PrintWriter
  3. // add the class Service and modify the class Application
  4. public class Service {
  5.     Reader reader;
  6.     Writer writer;
  7.     public void copy(){
  8.         int c=0;
  9.         while(c!=reader.read())
  10.             writer.write();
  11.     }
  12. }
  13. public class Application {
  14.     public void function(){
  15.         Service service=new Service();
  16.         service.copy();
  17.     }
  18. }
  控制反转 (inversion of control)
  用于消除框架和类库之间的依赖关系
  框架和类库最重要的区别是:框架是一个“半成品”的应用程序,而类库只包含了一系列可被应用程序调用的类。
  在面向对象领域,“回调函数”的替代物就是“模板方法模式”,也就是“好莱坞原则”(不要调用我们,让我们调用你)。
  应用程序和框架系统之间的依赖关系的特点:
  1.应用程序和框架系统之间实际上是双向调用,双向依赖的关系
  2.依赖倒置原则可以减弱应用程序到框架之间的依赖关系
  3.“控制反转”及具体的模板方法模式可以消解框架到应用程序之间的依赖关系,这也是所有框架系统的基础
  4.框架系统可以独立重用
  依赖注入(dependency injection)
  1.抽象接口隔离了使用者和实现者之间的依赖关系,但创建具体实现类的实现对象仍会造成对于具体实现的依赖。
  2.采用依赖注入可以消除这种创建依赖性,使用依赖注入后,某些类完全是基于抽象接口编写而成的,这可以最大限度的适应需求的变化  

点击(此处)折叠或打开

  1. //example
  2. // keep the classes: Reader, Writer, KeyboardReader, PrintWriter
  3. // modify the class Service and the class Application
  4. public class Service {
  5.     Reader reader;
  6.     Writer writer;
  7.     public void copy(){
  8.         int c=0;
  9.         while(c!=reader.read())
  10.             writer.write();
  11.     }
  12.     public Service(Reader reader,Writer writer){
  13.         this.reader=reader;
  14.         this.writer=writer;
  15.     }
  16. }
  17. public class Application {
  18.     KeyboardReader reader=new KeyboardReader();
  19.     PrintWriter writer = new PrintWriter();
  20.     public void function(){
  21.         Service service=new Service(reader, writer);
  22.         service.copy();
  23.     }
  24. }
  结论
  分离接口和实现是人们有效的控制依赖关系的最初尝试,而纯粹的抽象接口更好的隔离了互相依赖的两个模块,“依赖倒置”和“控制反转”原则从不同的角度描述了利用抽象接口消除耦合的动机。设计模式正是这一动机的完美体现。依赖注入模式可以把具体类的创建过程集中到合适的位置,这一动机和创建型模式有相似之处。
  
  ps:原文中的例子是画图的,这里不太好贴图,就写成代码了,顺便也可以复习一下OO的一些概念

阅读(419) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~