1. 内聚和耦合舉例
内聚和耦合是衡量子產品獨立性的兩種标準。
内聚——衡量一個子產品内部各元素之間的關系;耦合——衡量子產品間的關系。
1.1 内聚類型
1) 功能内聚:一個子產品隻完成一個單一功能。例:使用者權限子產品,該子產品隻負責與權限相關的實作。
2) 分層内聚:分層實作,上層能通路底層,底層不可通路上層。例:業務邏輯層能通路資料庫實作層,反之不可。
3) 通信内聚:通路相同資料的操作集中放到一個類或子產品中實作。例:對資料庫中某個表的增删改查定義在一個類中實作。
4) 順序内聚:子產品内的處理按照順序執行,且前者的輸出做為後者的輸入。例:将一個集合内的元素按指定規則排序,然後将排序後的集合輸出。
5) 過程内聚:子產品内部的處理按照順序執行,前者與後者之間沒有資料傳遞。例:先校驗參數的合法性,校驗通過後将參數在控制台輸出。
6) 暫時内聚:子產品内的操作是為了完成某一特定要求或狀态。
7) 實用内聚:子產品各部分之間沒有聯系或聯系松散。例:一個處理字元串的工具類。
内聚舉例: 參見EmployeeManager類中的各個方法
通信内聚: getEmployeeAge(Date birthDate)與isEmployeeRetired(Date birthDate)間存在通信内聚。
public class EmployeeManager {
// 功能内聚
private int getEmployeeAge(Date birthDate) {
int employeeAge = 0;
// TODO: 用目前日期計算與出生日期計算員工年齡
return employeeAge;
}
// 功能内聚
private boolean isEmployeeRetired(Date birthDate) {
int employeeAge = getEmployeeAge(birthDate);
if (employeeAge > 60) {
return true;
} else {
return false;
}
}
// 順序内聚
private boolean isEmployeeRetired(Date birthDate) {
int employeeAge = 0;
// TODO: 用目前日期計算與出生日期計算員工年齡
if (employeeAge > 60) {
return true;
} else {
return false;
}
}
// 邏輯内聚
private void printEmployeeSalary(int flag, int daySalary) {
int monthSalary = daySalary * 30;
int yearSalary = monthSalary * 12;
switch (flag) {
case 0:
// 列印日工資;
System.out.println(daySalary);
case 1:
// 列印月工資;
System.out.println(monthSalary);
case 2:
// 列印年工資;
System.out.println(yearSalary);
default:
// 列印月工資;
System.out.println(monthSalary);
}
}
// 過程内聚, 暫時内聚
private void printEmployeeInfo(Employee employee){
String name = employee.getName();
String sex = employee.getSex();
String address = employee.getAddress();
StringBulider printInfo = new StringBuilder();
printInfo.append("雇員的個人資訊————");
printInfo.append("姓名:");
printInfo.append(name);
printInfo.append(" | 性别:");
printInfo.append(sex);
printInfo.append(" | 位址:");
printInfo.append(address);
System.out.println(printInfo.toString());
}
}
1.2 耦合類型
1) 内容耦合:類Employee與TestB間存在内容耦合
public class Employee {
// 雇員目前年齡
public int curAge ;
// 雇員還有多少年退休
public int retireYear;
}
public class TestB {
private void printEmployeeInfo(){
Employee employeeA = new Employee();
employeeA.curAge = 20;
employeeA.retireYear = 65 - employeeA.curAge;
System.out.println("employeeA curAge is ", employeeA.curAge);
System.out.println("employeeA retireYear is ", employeeA.retireYear);
}
}
2) 共用耦合:類ScoreUtil與TestA間存在共用耦合
public class ScoreUtil {
public static int MinScore = 60;
public static int getAvgScore(int score1, int score2){
int sumScore = score1 + score2;
return sumScore/2;
}
}
public class TestA {
private void printScoreLevel(){
int score1 = 50;
int score2 = 100;
int avgScore = ScoreUtil.getAvgScore(score1, score2);
if(avgScore>ScoreUtil.MinScore){
System.out.println("Score is higher than min score.");
}else{
System.out.println("Score is lower than min score.");
}
}
}
3) 控制耦合:類ScoreUtil與TestA間存在控制耦合
public class ScoreUtil {
public static int getScore(boolean isGetAvg){
int score = 0;
if(isGetAvg){
//TODO get avg score
}else{
//TODO get max score }
return score;
}
}
public class TestA {
private int getAvgScore(){
return ScoreUtil.getScore(true);
}
}
4) 資料耦合:類ScoreUtil與TestA間存在資料耦合
public class ScoreUtil {
public static int getAvgScore(int score1, int score2){
int sumScore = score1 + score2;
return sumScore/2;
}
}
public class TestA {
private void printAvgScore(){
int score1 = 50;
int score2 = 100;
System.out.println(ScoreUtil.getAvgScore(score1, score2));
}
}
5) 印記耦合:printStudentNames和printStudentAvgAge之間存在印記耦合
import java.util.List;
public class TestB {
private void printStudentNames(List<Student> students){
for(Student student: students){
System.out.println(student.getName());
}
}
private void printStudentAvgAge(List<Student> students){
int totalAge = 0;
for(Student student: students){
totalAge = totalAge + student.getAge();
}
System.out.println(totalAge/students.size());
}
}
6) 類型使用耦合: 印記耦合的例子中的TestB類與Student類存在類型調用耦合
7) 例程調用耦合: 印記耦合的例子中的TestB類中的printStudentNames()調用了Student類中的getName(),存在例程調用耦合。
8) 包含/導入耦合:印記耦合的例子中的TestB類中引入了java.util.List。
9) 外部耦合:main方法與getStudentAvgScore方法,printAvgScore方法存在外部耦合
public class Test {
public static void main(String[] args) {
int avgScore = getStudentAvgScore();
printAvgScore(avgScore);
}
private static int getStudentAvgScore(){
int avgScore = 0;
//TODO
return avgScore;
}
private static void printAvgScore(int avgScore){
}
}
2. 進度條列示

2.1 代碼行數累積線段圖
2.2 部落格字數累積線段圖
3. PSP
job | type | date | start | end | total(min) |
寫随筆 | 随筆 | 2016.4.20 | 12:30 | 13:15 | 45 |
添加耦合例子 | 2016.4.21 | 21:30 | 22:51 | 81 | |
添加聚合例子,進度條,部落格字數累積線段圖 | 2016.4.22 | 12:00 | 13:02 | 62 |
4. 工作量表
代碼行數 | 部落格字數 | 知識點 |
第七周 | 1380 | β釋出 |