码迷,mamicode.com
首页 > 其他好文 > 详细

如何避免类之间的循环依赖

时间:2015-01-13 21:10:38      阅读:411      评论:0      收藏:0      [点我收藏+]

标签:

      最近在看《Java应用架构设计 模块化模式与OSGi》,深有感触,在此做些总结。(电子版可以在Java1234.com上下载到)

      在使用Java开发中,各种依赖不可避免。比如类之间的继承,jar包之间的相互依赖。依赖在某种程度上不可避免,但是过多的依赖势必会增加系统的复杂性,使代码难以阅读,从而成为团队开发的阻碍。循环依赖尤其糟糕。

     循环依赖存在与多种实体之间,尤其是类、包、模块之间。当两个类相互引用时,就会出现循环依赖。下面摘抄书中的一个例子。

     如图1.1所示,有Customer和Bill两个类。在本例中,Customer有一个Bill的实例列表,而Bill实例也引用Customer来计算折扣总额。这也成为双向关联(bidirectional association)。对于维护和测试,这将是一个将是一个问题,因为在不引用另一个类的情况下,你不能单独的对其中一个类做任何事情。

  技术分享

图1.1 类之间的循环依赖

      代码清单1.1展示了Customer类,代码清单1.2展示了Bill类。(为了简化,每个类的特定部分进行了省略。)在这里清楚展示了循环依赖。  

技术分享
package com.scott.cust;

import java.util.*;
import java.math.BigDecimal;
import com.scott.bill.*;

public class Customer {
   private List<Bill> bills;
   //特定Customer的折扣根据订单数目计算
   public BigDecimal getDiscountAmount() {
       if (bills.size() > 5) {
           return new BigDecimal(0.1);
       } else {
           return new BigDecimal(0.03);
       }
   }
   
   public void createBill() {
       Bill bill = new Bill(this);
       if (bills == null) {
           bills = new ArrayList<Bill>();
       }
       bills.add(bill);
   }

}
代码清单1.1 Customer
技术分享
package com.scott.bill;

import com.scott.cust.*;
import java.math.BigDecimal;

public class Bill {
   private Customer customer;
   
   public Bill(Customer customer) {
        this.customer = customer;   
   }
   
   public BigDecimal pay() {
       BigDecimal discount =  new BigDecimal(1),subtract(
            this.customer.getDiscountAmount()).setScale(2,
            BigDecimal.ROUND_HALF_UP);
       //确认折扣和应付款代码省略
       return paidAmount;

  }

}
代码清单1.2 Bill

      可以有多种方式打破循环依赖(笔者目前所知就是引入抽象),其中之一就是引入抽象,如图1.2所示。现在,借助mock的DiscountCaculator,Bill就可以容易的进行(单元)测试了。当然,测试Customer依旧需要Bill的参与。单着不是循环的问题了,这里暂时不做讨论。很显然,引入DiscountCalculator打破了Customer和Bill类之间依赖。但是,它能打破所有的循环依赖吗,包括可能存在与模块之间的?

技术分享

图1.2 打破循环   

代码清单1.3展示了修改后的Customer类,它实现了DiscountCalculator接口,改接口如程序清单4.4所示。

技术分享
package com.scott.cust;

import java.util.*;
import java.math.BigDecimal;
import com.scott.bill.*;

public class Customer implements DiscountCalculator {
   private List<Bill> bills;
   //特定Customer的折扣根据订单数目计算
   public BigDecimal getDiscountAmount() {
       if (bills.size() > 5) {
           return new BigDecimal(0.1);
       } else {
           return new BigDecimal(0.03);
       }
   }
   
   public List<Bill> getBills() {
       return this.bills;
   }

   public void createBill() {
       Bill bill = new Bill(this);
       if (bills == null) {
           bills = new ArrayList<Bill>();
       }
       bills.add(bill);
   }

}
代码清单1.3 修改后的Customer
技术分享
package com.scott.bill;

import java.math.BigDecimal;

public interface DiscountCalculator {
    public BigDecimal getDisCountAmount();
}
代码清单1.4 DiscountCalculator

 

如何避免类之间的循环依赖

标签:

原文地址:http://www.cnblogs.com/scottwang/p/4222323.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!