電子科大軟件系統架構設計——軟件建模詳細設計

文章目錄

  • 軟件建模詳細設計概述
    • 軟件建模詳細設計目標
    • 軟件建模詳細設計原則
      • 開閉原則
      • 里氏 (Liskov) 替換原則
      • 依賴倒置原則
      • 接口分離原則
      • 單一職責原則
      • 最少知識原則(迪米特法則)
      • 高內聚原則
      • 松耦合原則
      • 可重用原則
    • 軟件建模詳細設計內容
  • UML 軟件靜態結構視圖建模
    • 軟件靜態結構細化設計
    • 類的聚合關系細分
      • 專屬聚合 (Exclusive0wns)
      • 從屬聚合 (0wns)
      • 擁有聚合 (Has)
      • 成員聚合 (Member)
    • 泛化與繼承
    • 實現繼承
      • 擴展繼承
      • 限制繼承
      • 方便繼承
    • 高級類圖建模
      • 可見性
      • 導出信息
      • 限定關聯
      • 關聯類與具體化類
    • 接口與抽象類
      • 接口
      • 抽象類
      • 接口與抽象類的區別
    • 類內聚與耦合
      • 類內聚與耦合的啟發規則
      • 類耦合的種類
      • 類之間 6 種關系的耦合強度依次增強
      • 迪米特法則應用
    • 設計類圖建模實踐
  • UML軟件動態交互視圖建模
    • 順序圖
    • 通信圖
    • 類操作
      • 發現操作
      • 類操作的表示
    • 順序圖高級交互技術
      • 創建與銷毀臨時對象
      • 片段
      • 交互引用
  • UML軟件狀態機視圖建模
  • UML 軟件的實現視圖建模
    • 實現視圖
    • 構件圖
      • 構件和構件之間的依賴關系
      • 構件與接口之間的關系
      • 端口
      • 端口連接
    • 部署圖
    • 包圖
      • 包的可見性
      • 包的嵌套
      • 包圖
  • 圖書借閱管理系統軟件建模設計實踐
    • 系統需求
    • 系統靜態模型設計
    • 系統動態模型設計
      • 圖書搜索功能邏輯設計
      • 圖書借閱功能邏輯設計
      • 圖書歸還功能邏輯設計
      • Book對象的狀態機圖設計
      • Borrower對象的狀態機圖設計
      • 靜態結構的類圖模型細化設計

軟件建模詳細設計概述

軟件建模詳細設計目標

軟件建模詳細設計是在軟件架構模型設計基礎上,對系統中各模型進一步細化設計,給出軟件程序實現的設計方案。

軟件建模詳細設計原則

開閉原則

  • 軟件實體(類、構件等)應該對功能擴展具有開放性,對代碼修改具有封閉性。
  • 當應用需求改變時,在不修改軟件實體源代碼的前提下,就可以擴展模塊的功能,使其滿足新的需求。

案例:“環境監測器”功能構件設計

image-20231222200751781

開閉原則設計的好處:

  • 在不修改原有代碼基礎上,可以擴展新功能。
  • 提高代碼的可復用性及可維護性。

里氏 (Liskov) 替換原則

  • 子類可以擴展基類的功能,但不能改變基類原有的功能。
  • 子類在繼承基類時,除了添加新的方法且完成新增功能外,不要重寫基類的方法代碼。
  • 子類必須遵守基類與外部類之間的隱含約定。

image-20231222201247864

里氏替換原則設計的好處:

  • 解決了繼承重寫父類帶來的可復用性變差問題。
  • 提高代碼的可復用性及可維護性。

案例:鳥類飛行時間計算模塊程序設計

image-20231222202235280

//鳥類
class Bird {protected double flySpeed;public void setSpeed(double speed) {flySpeed = speed;}public double getFlyTime(double distance) {return (distance / flySpeed);}
}//燕子類
class Swallow extends Bird {
}//幾維鳥類
class BrownKiwi extends Bird {public void setSpeed(double speed) {flySpeed = 0;}
}

image-20231222213807148

package principle;public class LSPtest {public static void main(String[] args) {Bird bird1 = new Swallow();Bird bird2 = new BrownKiwi();bird1.setSpeed(120);bird2.setSpeed(120);System.out.println("如果飛行300公里: ");try {System.out.println("燕子將飛行" +bird1.getFlyTime(300) + "小時.");System.out.println("幾維鳥將飛行" +bird2.getFlyTime(300) + "小時.");} catch (Exception err) {System.out.println("發生錯誤了!");}}
}

按照里氏替換原則重新設計該模塊

image-20231222220441588

完整代碼:

// 動物類
class Animal {protected double runSpeed;public void setRunSpeed(double speed) {runSpeed = speed;}public double getRunTime(double distance) {return (distance / runSpeed);}
}// 鳥類
class Bird extends Animal {protected double flySpeed;public void setFlySpeed(double speed) {flySpeed = speed;}public double getFlyTime(double distance) {return (distance / flySpeed);}
}// 燕子類
class Swallow extends Bird {// 燕子類可以繼承 Bird 類的飛行行為
}// 幾維鳥類
class BrownKiwi extends Animal {// 幾維鳥不能飛,所以我們不實現飛行相關的方法// 而是使用 Animal 類的跑步行為// 如果需要,這里可以覆蓋跑步速度設置方法或行為
}

依賴倒置原則

  • 基于抽象類編程,不依賴具體類編程。
  • 面向接口編程,不要面向實現編程。

image-20231222220812371

依賴倒置原則設計的好處:

  • 降低客戶類與實現類之間的耦合性,容易實現代碼可擴展性。
  • 降低并行開發可能出現的風險性。

案例:顧客購物模塊程序設計

顧客類 (Customer) 通過韶關網店(ShaoguanShop)類實現購物,其代碼如下:

class Customer {public void shopping(ShaoguanShop shop) {//購物System.out.println(shop.sell());}
}

顧客若想從婺源網店 (WuyuanShop) 購物,需要對顧客類 (Customer )代碼修改:

class Customer {public void shopping(WuyuanShop shop) {//購物System.out.println(shop.sell());}
}

解決方法:定義“婺源網店”和“韶關網店”的共同接口 Shop ,顧客類 (Customer )面向該接口編程,其代碼修改如下:

image-20231222221518622

class Customer {public void shopping(Shop shop) {//購物System.out.println(shop.sell());}
}

完整代碼:

// 定義 Shop 接口
interface Shop {String sell();
}// 韶關網店實現 Shop 接口
class ShaoguanShop implements Shop {@Overridepublic String sell() {// 實現賣出商品的方法,返回結果return "韶關網店銷售的商品";}
}// 婺源網店實現 Shop 接口
class WuyuanShop implements Shop {@Overridepublic String sell() {// 實現賣出商品的方法,返回結果return "婺源網店銷售的商品";}
}// 顧客類,面向 Shop 接口編程
class Customer {public void shopping(Shop shop) {// 購物System.out.println(shop.sell());}
}

接口分離原則

  • 一個構件對外應提供不同服務的專用接口,而不要試圖去建立一個很龐大的接口供所有依賴它的構件去調用,避免客戶端依賴不必要的接口方法
  • 提供者構件應該為每個不同訪問構件類型提供一個特定的接口

image-20231222223341534

接口分離原則設計的好處:

  • 符合高內聚低耦合設計思想,提高代碼可擴展性。
  • 使得類具有很好的可讀性、可擴展性和可維護性。

案例:學生成績管理程序

image-20231222223506809

  • 學生成績管理程序一般包含插入成績、刪除成績、修改成績、計算總分、計算均分、打印成績信息、查詢成績信息等功能。
  • 如果將這些功能全部放到一個接口中對外提供訪問服務,這顯然不太合理。
  • 合理的做法是對外提供不同的功能服務訪問接口。

單一職責原則

  • 一個類應該有且僅有一個功能職責,否則該類應該被拆分。
  • 單一職責原則的核心就是控制類的粒度大小,將對象解耦,提高其內聚性。

單一職責原則設計的好處:

  • 降低類的復雜度。一個類只負責一項職責,其代碼邏輯肯定要比負責多項職責簡單得多。
  • 提高類代碼的可讀性。復雜性降低,自然其可讀性會提高。
  • 提高類代碼的可維護性。可讀性提高,那自然更容易維護了。

案例:學生工作管理

image-20231222225406643

學生工作主要包括學生生活輔導和學生學業指導兩個方面的工作:

  • 生活輔導主要包括班委建設、出勤統計、心理輔導、費用催繳、班級管理等工學業指導主要包括專業引導、學習輔導、科研指導、學習總結等工作。
  • 如果將這些工作交給一位老師負責顯然不合理,好的做法是生活輔導由輔導員負責,學業指導由學業導師負責。

最少知識原則(迪米特法則)

迪米特法則的定義是:只與你的朋友交談,不跟“陌生人”說話。在程序設計中,如果兩個軟件實體沒有直接關系,那么就不直接調用,可以通過第三方轉發該調用。

迪米特法則具有以下好處:

  • 降低了類之間的耦合度,提高了模塊的相對獨立性。
  • 由于耦合度降低,從而提高了類的可復用性和系統的擴展性。

案例:明星與經紀人的關系

image-20231222230017098

  • 明星需全身心投入藝術,所以許多日常事務交給經紀人去處理,如與粉絲的見面會,與媒體公司的業務洽淡等。
  • 經紀人是明星的朋友,而粉絲和媒體公司對明星來講是陌生人。

高內聚原則

內聚性意味著構件或者類只封裝那些密切關聯的屬性和操作。

按照內聚性的級別,內聚性分為以下三種,它們的內聚性依次變弱:

  • 功能內聚:模塊內的所有元素緊密配合完成同一個功能,即滿足單一職責原則。
  • 分層內聚:系統采用分層結構,高層能夠訪問低層服務,但低層不能訪問高層服務。
  • 通信內聚:模塊內的所有元素都訪問相同數據。通信內聚通常用于數據的查詢、訪問和存儲。

一般來說,內聚性越高,構件越易于實現、測試和維護。

image-20231222231011912

松耦合原則

耦合性指不同對象之間相互關聯的程度。如果一個對象過多地依賴于其它對象來完成自己的工作,這會增加測試、修改的難度,同時降低了對象的可重用性和可移植性。

在詳細設計中要盡可能保持對象之間松耦合。但是軟件必須進行內部和外部的通信,因此耦合是必然存在的。當兩個對象必須相互聯系時,應該通過類的公共接口實現耦合,不應該直接依賴于類的實例。

補充例子:

// 定義一個通信接口
interface Communicator {void sendMessage(String message);String receiveMessage();
}// 實現Communicator接口的Email類
class EmailCommunicator implements Communicator {public void sendMessage(String message) {System.out.println("Sending email with message: " + message);}public String receiveMessage() {// 假設接收到消息return "Email message received";}
}// 實現Communicator接口的SMS類
class SMSCommunicator implements Communicator {public void sendMessage(String message) {System.out.println("Sending SMS with message: " + message);}public String receiveMessage() {// 假設接收到消息return "SMS message received";}
}// 使用Communicator接口的Client類
class Client {private Communicator communicator;public Client(Communicator communicator) {this.communicator = communicator;}public void communicate() {communicator.sendMessage("Hello World!");System.out.println(communicator.receiveMessage());}
}// 在應用程序中使用Client和Communicator
public class CommunicationApp {public static void main(String[] args) {Communicator email = new EmailCommunicator();Communicator sms = new SMSCommunicator();Client emailClient = new Client(email);Client smsClient = new Client(sms);emailClient.communicate();smsClient.communicate();}
}

在這個例子中,Client 類不直接與 EmailCommunicatorSMSCommunicator 類耦合。相反,它通過 Communicator 接口與它們通信。這允許 Client 類在不知道通信細節的情況下發送和接收消息。因此,如果將來引入了一個新的 Communicator 實現,例如 WhatsAppCommunicatorClient 類不需要任何修改就能使用它,只需在創建 Client 實例時傳入新的通信器即可。這就是通過類的公共接口實現耦合的一個典型例子。

可重用原則

  • 為了提高工作效率、減少錯誤、降低成本,要充分考慮軟件元素的重用性
  • 重用性有兩個方面的含義:盡量復用已有的類代碼,如開發環境提供的類庫;在設計新類時考慮將來的可重用性。
  • 設計一個可重用的軟件比設計一個普通軟件的代價要高,但是隨著這些軟件被重用次數的增加,分攤到它的設計和實現成本就會降低。

補充例子:

import java.util.ArrayList;
import java.util.List;// 一個通用的接口定義了操作的契約
interface Operable {void operate();
}// 一個具體的類實現了Operable接口
class Printer implements Operable {@Overridepublic void operate() {System.out.println("Printing a document...");}
}// 另一個具體的類實現了Operable接口
class Scanner implements Operable {@Overridepublic void operate() {System.out.println("Scanning a document...");}
}// 設計一個工作流程類,它可以利用Operable接口操作任何設備
class Workflow {private List<Operable> operations = new ArrayList<>();public void addOperation(Operable operable) {operations.add(operable);}public void runAll() {for (Operable operable : operations) {operable.operate();}}
}// 演示如何重用Workflow類來操作不同的設備
public class OfficeAutomationApp {public static void main(String[] args) {// 創建設備的實例Printer printer = new Printer();Scanner scanner = new Scanner();// 創建工作流并添加操作Workflow officeWorkflow = new Workflow();officeWorkflow.addOperation(printer);officeWorkflow.addOperation(scanner);// 運行所有操作officeWorkflow.runAll();}
}

在這個例子中,Operable 接口允許我們定義一個可以操作任何設備的通用契約。PrinterScanner 類都實現了這個接口,使得它們可以在 Workflow 類中互換使用。這樣的設計不僅提高了類的重用性,而且在設計新類時也考慮到了將來的可重用性。例如,如果我們想添加一個新設備類如 FaxMachine,我們只需要讓它實現 Operable 接口,就可以輕松地添加到現有的工作流程中而不需要修改 Workflow 類的代碼。

此外,這個例子還展示了如何復用Java開發環境提供的類庫,例如 ArrayList 類,來管理 Operable 對象的集合。這種復用標準類庫可以提高開發效率,減少錯誤,并降低開發成本。

以下客戶功能模塊存在什么設計問題?該如何完善?

接口分離原則, IClient 接口提供的方法太多或不是所有的客戶端都需要這些方法,它違反了接口分離原則。客戶端不應該被迫依賴于它們不使用的方法。 根據不同的職責將 IClient 接口拆分為更小的接口。詳細代碼如下:

// 接口負責連接管理
public interface IConnectionManager {void connect();void disconnect();
}// 接口負責數據的發送和接收
public interface IDataTransfer {void send();void receive();
}// 客戶端類實現這兩個接口
public class Client implements IConnectionManager, IDataTransfer {@Overridepublic void connect() {// 實現連接邏輯}@Overridepublic void disconnect() {// 實現斷開連接邏輯}@Overridepublic void send() {// 實現發送數據邏輯}@Overridepublic void receive() {// 實現接收數據邏輯}
}

問題探討:以下客戶數據圖形分析模塊存在什么設計問題?該如何完善?

image-20231223123236184

違背單一職責原則,應將該類進行拆分,CustomerDataChart 類負責圖表的創建和顯示,一個 CustomerDAO 類負責數據訪問操作,以及一個 DBUtil 類負責數據庫連接。

代碼如下:

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;class DBUtil {public Connection getConnection() {// 實現數據庫連接的邏輯// 例如使用 JDBC 連接到數據庫return null; // 應返回實際的數據庫連接對象}
}class CustomerDAO {private DBUtil util;public CustomerDAO(DBUtil util) {this.util = util;}public List<Customer> findCustomers() {// 使用 util.getConnection() 獲取數據庫連接// 執行查詢并返回客戶列表return new ArrayList<>(); // 應返回實際查詢到的客戶列表}
}class CustomerDataChart {private CustomerDAO dao;public CustomerDataChart(CustomerDAO dao) {this.dao = dao;}public void createChart() {// 使用 dao.findCustomers() 獲取數據// 根據獲取的數據創建圖表}public void displayChart() {// 顯示圖表的邏輯}
}public class Main {public static void main(String[] args) {// 創建 DBUtil 實例DBUtil dbUtil = new DBUtil();// 使用 DBUtil 實例來創建 CustomerDAO 實例CustomerDAO customerDAO = new CustomerDAO(dbUtil);// 使用 CustomerDAO 實例來創建 CustomerDataChart 實例CustomerDataChart dataChart = new CustomerDataChart(customerDAO);// 創建圖表dataChart.createChart();// 顯示圖表dataChart.displayChart();}
}

圖形展示如下:

image-20231223123656209

軟件建模詳細設計內容

  • 在分析類基礎上,對軟件靜態結構模型的類圖進行詳細設計。各個功能構件均需給出設計類模型。
  • 針對構件功能,分析對象之間的交互關系,給出功能構件邏輯實現的動態行為交互圖模型詳細設計。
  • 分析對象生命周期的狀態變化,給出對象狀態變遷的狀態機圖模型詳細設計。
  • 對反映軟件物理實現模型的構件圖部署圖進行詳細設計。

UML 軟件靜態結構視圖建模

軟件靜態結構細化設計

  • 靜態結構視圖用來表示軟件系統的類程序組成結構,同時也反映各個類中封裝的數據與操作方法。
  • 靜態結構視圖支撐面向對象程序編程。

image-20231223131811928

類的聚合關系細分

專屬聚合 (Exclusive0wns)

專屬聚合是類之間語義最強的聚合,部分類與整體類之間滿足 4 個條件:

  1. 部分類對整體類具有存在依賴性,刪除整體類時,部分類也被刪除。
  2. 具有傳遞性,如果對象 C1是 B1 的一部分,并且 B1 是 A1 的一部分, C1 也是 A1 的一部分。
  3. 具有非對稱性,如果 B1 是 A1 的一部分,則 A1 不是 B1 的一部分。
  4. 具有固定性,如果 B1 是 A1 的一部分,則它絕不是 Ai (i!=1)的一部分。

image-20231223133005855

從屬聚合 (0wns)

從屬聚合的語義比專屬聚合稍弱,部分類與整體類之間滿足 3 個條件:

  1. 部分類對整體類具有存在依賴性,刪除整體類時,部分類也被刪除。
  2. 具有傳遞性,如果對象 C1 是 B1 的一部分,并且 B1 是 A1 的一部分,則 C1 是 A1 的一部分。
  3. 具有非對稱性,如果 B1 是 A1 的一部分,則 A1 不是 B1 的一部分。

image-20231223133208338

擁有聚合 (Has)

擁有聚合的語義比從屬聚合弱,部分類與整體類之間滿足 2 個條件:

  1. 具有傳遞性,如果對象 C1 是 B1 的一部分,并且 B1 是 A1 的一部分,則 C1 是 A1 的一部分。
  2. 具有非對稱性,如果 B1 是 A1 的一部分,則 A1 不是 B1 的一部分。

image-20231223133256847

成員聚合 (Member)

成員聚合的語義最低,僅僅是將一組對象組合在一起。

  • 不具有存在依賴性、傳遞性、非對稱性、固定性。
  • Member 聚合具有組合獨立對象的特征。
  • 表示一組對象作為一個高層復合對象來考慮。
  • 一個對象可以同時屬于一個以上的復合對象,因此 member 聚合的多重性可以是多對多。

image-20231223133531574

泛化與繼承

  • 泛化是指多個類的公共特征抽象到一個更一般化的類中,它描述類之間的一般與具體關系。
  • 繼承是指子類復用基類(超類)屬性與操作的機制。

image-20231223133655398

實現繼承

實現繼承是指在子類中組合基類(超類)的特征,并允許在必要時以新的實現來重載這些特征。

擴展繼承

image-20231223133923122

在擴展繼承中,子類組合來自超類的特征,并增加新的特征。

限制繼承

限制繼承是指子類組合來自超類的特征,并重載部分繼承來的特征。

image-20231223134137099

問題:重載導致子類沒有包括超類的所有特征,會帶來維護上的問題,可替換性原則失效。

方便繼承

某些類之間具有一定相似的實現,但它們之間不存在泛化關系,即沒有概念上的分類關系。方便繼承是指將它們中一個類作為其它類的超類。

image-20231223134310533

問題:子類沒有包括超類的所有特征,子類與超類之間沒有泛化關系,可替換性原則無效。盡量避免采用這種方式實現繼承。

高級類圖建模

軟件開發的實際情況很復雜,復雜的問題不會有簡單的解決方案。本節引入類圖建模的高級概念,包括:

  • 可見性
  • 導出信息
  • 限定關聯
  • 關聯類與具體化類

可見性

通過設置可見性可以確定類內部的封裝程度,決定其他類能否訪問該類的元素。應用于類的屬性和操作的可見性類型包括:

  • + public公共可見性: 該元素對任何類都可見;
  • - private私有可見性: 該元素只對本類可見;
  • # protected保護可見性: 該元素對本類及子類可見;
  • ~ package包可見性: 該元素對同一包中的元素可見.

在設計良好的面向對象系統中,大多數操作是公共的,大多數屬性是私有的。

image-20231223135711089

public class Visibility {private int privateAttribute;public int publicAttribute;protected int protectedAttribute;int packageAttribute; // 默認訪問修飾符,也稱為包訪問權限private void privateOperation() {}public void publicOperation() {}protected void protectedOperation() {}void packageOperation() { // 默認訪問修飾符,也稱為包訪問權限}
}

( 1 )保護可見性

  • 保護可見性指類的屬性或操作對本類及其子類可見。
  • 應用于繼承的情況,允許子類對象訪問父類對象中的屬性和操作。

image-20231223140102952

( 2 )包可見性

  • 具有包可見性類的屬性和操作能夠被處于同一包中的其他類訪問。
  • 包可見性是 Java 語言默認的可見性。

image-20231223140200495

( 3 )友元可見性友元可見性用于 c++語言。當一個類需要訪問另一個類的私有屬性或操作時,可以采用友元可見性,在授予友元關系的類中聲明友元操作。

image-20231223140224108

class Book {
private:void putOnBookShelf();
};class BookShelf {
public:friend void Book::putOnBookShelf();
};

導出信息

導出信息是指從其他元素計算得到的信息。它作為一種冗余信息,其目的是為了增加可讀性和信息存取速度。導出信息包括導出屬性導出關聯。

  • 導出屬性是指可以由其他信息導出的屬性。
  • 導出關聯是指由其它關聯導出的關聯。
  • 導出信息的 UML 表示是在導出屬性名或導出關聯名前面加上一條斜線“/”。

image-20231223140818360

限定關聯

限定關聯是一對多或多對多關聯的約束條件表示。限定關聯在二元關聯的一端設定屬性限定符,即在框中給出一個或多個屬性用于約束條件。

image-20231223140934691

關聯類與具體化類

如果兩個類之間是多對多的關聯,且每個關聯實例都具有屬性值,這時可以使用關聯類。關聯類具有一個約束,要求對于每一對鏈接起來的類實例,只能作為關聯類的一個實例。如果不能滿足這個約束的話,就需要將關聯具體化,即使用一個具體化類來代替關聯類。這個具體化類與之前的兩個類均具有二元關聯。

image-20231223141222186

接口與抽象類

接口

接口用于定義一個類或者構件的功能操作函數集。

  • 接口定義一組操作,但不定義操作的實現。
  • 接口一般不定義屬性,只有定義操作,并且所有操作都隱含是公共的、抽象的可視性。
  • 在實現接口的類中,這些操作都要被實現。
  • 一個類可以實現多個接口,一個接口可以被多個類實現

image-20231223143811716

接口是一種特殊的類,所有的接口都是構造型為<<interface>>的類。在UML中,接口的表示方式有三種: 第一種是接口的圖標表示,第二種是接口的修飾表示,第三種是接口的構造型標簽表示。

image-20231223144103353

image-20231223144123081

  • 如果接口使用 構造型標簽表示,實現關系線是一條末端帶有空心三角的虛線,箭頭指向接口,虛線上可以加上構造型關鍵字《implement》。
  • 如果接口使用圖標表示,實現關系線則是一條實線,沒有箭頭,實線上也可以加上構造型關鍵字《implement》。
  • 一個類使用接口,表明該類依賴該接口,用指向接口的一條虛線箭頭表示,箭頭上可以加上構造型關鍵字《use》。

案例: IElectricalEquipment接口定義了turnOn操作和turnoff操作,TV類和Player類均實現了該接口,即實現了turnOn操作和turnoff操作,RemoteControl類使用了IElectricalEquipment接口。

image-20231223144513328

抽象類

抽象類指不具有實例的類,它通常作為父類,不創建實例對象。抽象類的子類可以實例化。

  • 抽象類一般至少有一個抽象操作。
  • 抽象類的作用是為其子類描述它們的公共屬性和行為。
  • UML 采用斜體表示抽象類的名稱,也可以使用 {abstract) 約束來表示。

image-20231223144739041

補充代碼:

// 定義一個 Vehicle 基類
abstract class Vehicle {private String color; // 車輛顏色屬性public Vehicle(String color) {this.color = color;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}// 定義一個抽象方法 drivepublic abstract void drive();
}// Plane 類繼承自 Vehicle
class Plane extends Vehicle {public Plane(String color) {super(color);}// 實現 drive 方法public void drive() {System.out.println("Plane is flying.");}
}// Bus 類繼承自 Vehicle
class Bus extends Vehicle {public Bus(String color) {super(color);}// 實現 drive 方法public void drive() {System.out.println("Bus is driving on the road.");}
}// Driver 類與 Vehicle 有關聯關系
class Driver {private Vehicle vehicle;// Driver 可以駕駛任何類型的 Vehiclepublic void driveVehicle(Vehicle vehicle) {this.vehicle = vehicle;vehicle.drive();}
}

接口與抽象類的區別

  • 抽象類是對一組具有相同屬性和方法、邏輯上有關系的類抽象。
  • 接口是對一組具有相同屬性和方法、邏輯上不相關的類抽象。
  • 抽象類可提供部分方法的代碼實現,而接口不實現任何方法的代碼實現。
  • 抽象類體現一種泛化關系,而接口體現契約關系。
  • 抽象是在問題域分析中發現,而是接口是在設計發現。

類內聚與耦合

類內聚是指類內部元素之間相關性的程度。類耦合是指類之間聯系的程度。

  • 內聚和耦合彼此相關聯,更強的內聚會導致更弱的耦合,反之亦然。

  • 良好的程序設計應確保在類的內聚與耦合之間達到良好平衡。

類內聚與耦合的啟發規則

為了取得類內聚和類耦合之間的平衡, Riel提出了一些啟發規則:

  • 屬性及其相關操作封裝在一個類中;
  • 類之間只通過公共接口產生依賴;
  • 每個類應該只實現單一職責功能;
  • 類中不存在一個操作子集只與一個屬性子集相關的情況;
  • 系統功能應盡可能在各個類中均勻分配。

類耦合的種類

( 1 ) x 類有屬性指向 Y 類的實例

( 2 ) x 類有方法引用了 Y 類的實例,如x 使用 Y 類對象作為局部變量;或者返回 Y 類對象

image-20231223145855463

( 3 ) x 類對象調用 Y 類對象方法發送消息

image-20231223150051051

( 4 ) Y 類是 X 類的直接或間接子類

image-20231223150243469

( 5 )X 類方法中輸入參數為 Y 類的實例。

image-20231223150330305

( 6 ) Y 類是一個接口,而 X 類實現了該接口。

image-20231223150352801

類之間 6 種關系的耦合強度依次增強

1 )依賴關系一耦合度最弱

image-20231223150456224

2 )關聯關系一耦合度其次弱

image-20231223150507795

3 )聚合關系一耦合度一般

image-20231223150609064

4 )組合關系一耦合度較高

image-20231223150621436

5 )繼承關系一耦合度高

image-20231223150654467

6 )實現關系一耦合度最高

image-20231223150736520

迪米特法則應用

類耦合對于對象之間協作實現特定功能是必要的,但它應該盡量被限制在類的層次內,即層內耦合,層間耦合應該最小化。

為了限制類間任意通信,采用迪米特法則(最少知識原則)設計,指明在類操作中只允許將以下對象作為消息目標,即沒有直接關系的類之間不交互通信,僅僅有直接關系類進行通信。

  • 當前對象本身
  • 當前操作中作為參數的對象
  • 當前對象的屬性指向的對象
  • 當前操作創建的對象
  • 全局變量引用的對象

設計類圖建模實踐

  • 設計類圖建模是在分析類圖基礎之上對系統分析類圖進行細化與完善設計,從而在設計層面描述系統的靜態結構。
  • 在設計類圖中除了詳細定義各種類屬性與方法外,還需定義類之間關系的設計約束。

Power Designer 建模實踐:雇員職位管理設計類圖建模

image-20231223151832857

ChatGPT4:

  1. Person 類
    • 屬性:name (String), sex (char)
    • 方法:getName() 返回 String,getSex() 返回 char
    • 這個類似乎代表了具有基本屬性如姓名和性別的普通人。
  2. Employee 類(繼承自 Person 類)
    • 屬性:username (String), password (String)
    • 方法:usernamepassword 的獲取和設置方法,一個接受用戶名和密碼并返回布爾值的 login() 方法,以及重寫的 getName()getSex() 方法。
    • Employee 類繼承自 Person 類,這意味著每個 Employee 都是 Person,但具有特定于雇員的額外屬性和行為,如登錄系統的憑證。
  3. Post 類
    • 屬性:postname (String)
    • 方法:getPostname() 返回 String,setPostname() 接受一個 String,addPost() 返回一個布爾值。
    • 這個類似乎代表 Employee 可以持有的職位或職稱。1..1 表示每個 Employee 有且僅有一個 Post
  4. Department 類
    • 屬性:departmentname (String)
    • 方法:departmentname 的獲取和設置方法,addDepartment() 返回布爾值。
    • 代表組織中的一個部門。每個 Employee 與一個 Department 關聯,而一個 Department 可以有多個雇員(1..* 關系)。
  5. Power 類
    • 屬性:powername (String)
    • 方法:powername 的獲取和設置方法。
    • 代表與 Post 關聯的權力或權限。每個 Post 有且僅有一個 Power,表示一對一的關系。
  6. Poweritem 類(繼承自 Power 類)
    • 屬性:itemname (String), isvalue (int)
    • 方法:itemnameisvalue 的獲取和設置方法,addItem() 返回布爾值。
    • 這個類繼承自 Power 類,暗示每個權限可以有多個 Poweritem 實例,這些是更具體的權限或許可。

類圖還展示了類之間的關聯關系:

  • 一個 Employee 與一個 Person 相關聯(繼承關系)。
  • 一個 Employee 可以有一個或多個 Post0..*1..1 的關系),但每個 Post 都確切地與一個 Employee 相關聯。
  • 每個 Post 與一個 Power 關聯,每個 Power 與一個 Post 關聯(1..1 關系)。
  • 一個 Department 可以有多個 Employee 實例,但每個 Employee 都與一個 Department 相關聯。

這個模型旨在管理組織中雇員的角色和責任。它捕捉了不同組織實體如人員、職位、部門以及與這些職位相關聯的權限之間的層次結構和關系。該系統可用于跟蹤員工的職位角色、所屬部門及其在組織內的相應權限。使用繼承和關聯確保了清晰、可維護的結構,能夠準確反映組織結構。

1 .分析說明如下模型中類之間設計該關系依據是什么?以及它們的耦合度高低。

2 .針對如下 UML 設計類圖給出 Vehicle 類、 Car 類、 Bus 類的 Java 編程代碼。

image.png

1)

2)

import java.util.ArrayList;
import java.util.List;// Vehicle.java
public interface Vehicle {void run();
}// Car.java
public class Car implements Vehicle {public String name;public List<Driver> drivers;public Car(String name) {this.name = name;this.drivers = new ArrayList<>();}@Overridepublic void run() {// Car的run實現}public void beforeRun(Oil oil) {// Car的beforeRun實現}public void addDriver(Driver driver) {this.drivers.add(driver);}
}// Bus.java
public class Bus extends Car {public Bus(String name) {super(name);}// Bus可能有特定的行為和屬性,這里只提供基礎構造方法
}

完整代碼:

import java.util.ArrayList;
import java.util.List;// Vehicle.java
interface Vehicle {void run();
}// Car.java
class Car implements Vehicle {public String name;public List<Driver> drivers;public Car(String name) {this.name = name;this.drivers = new ArrayList<>();}@Overridepublic void run() {// Car的run實現}public void beforeRun(Oil oil) {// Car的beforeRun實現}public void addDriver(Driver driver) {this.drivers.add(driver);}
}// Bus.java
class Bus extends Car {public Bus(String name) {super(name);}// Bus可能有特定的行為和屬性,這里只提供基礎構造方法
}// Driver.java
class Driver {public String name;public int age;public List<Car> cars;public Driver(String name, int age) {this.name = name;this.age = age;this.cars = new ArrayList<>();}public void addCar(Car car) {this.cars.add(car);}
}// Oil.java
class Oil {public String type;public Oil(String type) {this.type = type;}public void add() {// Oil的add方法實現}
}

UML軟件動態交互視圖建模

軟件動態交互視圖用于描述系統功能的對象之間動態交互行為。順序圖和通信圖均屬于動態交互模型圖。

順序圖

順序圖也稱序列圖,它按照從上至下順序描述對象之間的消息交互,其目的是展示功能邏輯的設計實現。

  • 順序圖由一組對象及它們之間的消息組成,強調消息的先后時間順序。
  • 順序圖也包括生命線、激活、片段等圖形元素。

image-20231223163902262

通信圖

通信圖是另一種類型的動態交互圖,它用于表現對象之間的協作關系。通信圖由對象以及其關聯組成,它強調對象間的連接關系,對象之間消息通信順序使用序列號表示。

image-20231223165901323

類操作

類操作(方法)是指類所能提供的服務或功能函數。類將一組操作函數作為服務提供給系統中的其他類訪問。

發現操作

  • 可從順序圖或通信圖的對象交互中發現類操作。順序圖和通信圖中的每一條消息,都必須有目標對象的一個操作為其服務。
  • 根據類的職責確定操作,如數據記錄創建、讀取、更新和刪除操作。

image-20231223170220267

類操作的表示

在 UML 中,類操作的表示語法為:

[可見性] 操作名稱 [(參數表)] [:返回類型] [{屬性字符串}]

操作名稱是動詞或動詞短語,單詞首字母小寫。如果有多個單詞,則將這些單詞連接起來,第一個單詞首字母小寫,其他單詞首字母大寫。

image-20231223170420445

ChatGPT4:

類圖代表了使用數據傳輸對象(DTO)模式的用戶注冊系統設計。這種模式在面向對象設計中常用于軟件應用子系統之間的數據傳輸。這里是類圖的每個部分的詳細解釋:

UserDTO 類:

這是一個簡單的 DTO 類,包含兩個屬性:

  • userAccount:一個 String 類型,用來存儲用戶的賬戶名。
  • userPassword:一個 String 類型,用來存儲用戶的密碼。

它還提供了兩個屬性的獲取和設置方法,允許其他類訪問和修改這些值:

  • getUserAccount():返回 userAccount 字符串。
  • setUserAccount(String userAccount):設置 userAccount 字符串。
  • getUserPassword():返回 userPassword 字符串。
  • setUserPassword(String userPassword):設置 userPassword 字符串。

RegisterForm 類:

這個類似乎代表用戶填寫的注冊表單。它包含:

  • userUserDTO 的一個實例,用來保存與用戶相關的表單數據。
  • userDaoIUserDAO 接口的一個實例(下面會解釋),可能用于將用戶添加到某種類型的數據存儲中。

IUserDAO 接口:

這是一個定義用戶數據訪問對象(DAO)契約的接口,包含以下方法:

  • addUser(UserDTO user):一個接受 UserDTO 對象并返回一個表示添加用戶到數據存儲是否成功的 boolean 值的方法。

OracleUserDAO 類:

這是 IUserDAO 接口的一個具體實現,專門設計用來與 Oracle 數據庫交互。它實現了 IUserDAO 接口的 addUser 方法。

關系

  • RegisterFormUserDTO 有一個組合關系,由實心菱形表示,意味著 RegisterForm 包含并控制 UserDTO 實例的生命周期。
  • RegisterFormIUserDAO 有一個關聯關系,由箭頭表示,意味著它使用 IUserDAO 接口來訪問用戶數據。
  • IUserDAOOracleUserDAO 有一個實現關系,由虛線和空心箭頭表示。這意味著 OracleUserDAO 承諾實現 IUserDAO 定義的契約。

案例:發現操作

image-20231223170723340

順序圖高級交互技術

創建與銷毀臨時對象

  • 當創建臨時對象時,發送者發出一個實例化消息后將創建臨時對象。
  • 當銷毀臨時對象時,發送者發出消息銷毀臨時對象,并回收其擁有的資源。
  • 在順序圖中,在對象的生命線上標記“×”符號,表示對象被銷毀。

image-20231223171503752

片段

在模塊功能詳細設計中,需要描述功能處理的控制邏輯,如展示條件分支循環處理,以及并行執行。在順序圖中采用不同類型的片段來表示這些控制邏輯。

UML 2.x中預定義了如下片段:

  • opt選項片段
  • alt條件片段
  • loop循環片段
  • para并行片段

(1) loop循環片段

在模塊功能邏輯設計中,使用loop片段表示重復執行一些操作。

image-20231223172428127

(2)para并行片段

在模塊功能邏輯設計中,使用para片段表示執行一些并行操作。

image-20231223172616562

(3)alt條件片段

在模塊功能邏輯設計中,使用alt片段表示根據條件執行操作。alt片段表達if-then-else邏輯。

image-20231223172942095

(4) opt選項片段

在模塊功能邏輯設計中,使用opt片段根據當條件執行選項操作。opt片段表達if…then邏輯。

image-20231223173118811

交互引用

在設計有較多相同處理邏輯的模塊時,可以采用交互引用復用已有處理邏輯,被引用的處理邏輯采用標簽 ref 標注。

image-20231223173248501

在如下訂單提交模塊序列圖模型中,包含了哪些處理邏輯?并分別說明各交互對象的對象類型。

image.png

訂單結賬和信用卡支付。

Customer、Payment Processor為參與者, Order Checkout、CreditCard Payment為控制類對象, Checkout Page為邊界類對象 ,Order、OrderItem、Item為實體類對象。

UML軟件狀態機視圖建模

狀態機圖是對系統中對象的狀態變化邏輯進行建模,它描述類對象隨時間變化的行為狀態,以及對象受事件影響如何進行狀態變遷。

狀態機圖建模步驟:

  • 發現對象狀態
  • 分析對象變遷的事件與條件
  • 建立對象狀態圖

案例:微波爐工作的狀態機圖

image-20231223175114284

ChatGPT4:

狀態:

  • Waiting(等待):微波爐的初始狀態,顯示時間,等待用戶輸入。
  • Full Power(全功率):微波爐在全功率模式下工作,功率設置為600W。
  • Half Power(半功率):微波爐在半功率模式下工作,功率設置為300W。
  • Set Time(設置時間):用戶設置微波爐的工作時間。
  • Enabled(啟用):微波爐門關閉,準備開始工作,顯示“Ready”。
  • Disabled(禁用):微波爐門開啟,不允許操作,顯示“Waiting”。
  • Operation(操作):微波爐開始工作。

轉換和觸發事件:

  • 用戶選擇全功率或半功率,微波爐進入相應的功率狀態。
  • 在任何功率狀態下,設置時間后,微波爐進入設置時間的狀態。
  • 當時間被設置后,如果微波爐門關閉,微波爐變為啟用狀態。
  • 如果微波爐門打開,微波爐將變為禁用狀態。
  • 從啟用狀態,開始操作將使微波爐進入操作狀態并開始加熱。
  • 用戶可以在任何時候取消操作,微波爐將返回到等待狀態。
  • 在操作結束后,微波爐將完成加熱過程并返回到等待狀態。

針對如下電梯對象的狀態機圖模型,如何編寫其Java控制程序?

image.png

代碼均為簡化代碼,參考思路即可:

1.定義電梯的狀態和事件:

public enum ElevatorState {IDLE,MOVING_UP,MOVING_DOWN,OPEN_DOORS,CLOSED_DOORS
}public enum ElevatorEvent {CALL_UP,CALL_DOWN,MOVE_UP,MOVE_DOWN,DOORS_OPEN,DOORS_CLOSE,TIMEOUT
}

2.創建電梯的控制類

public class ElevatorControl {private ElevatorState currentState;public ElevatorControl() {this.currentState = ElevatorState.IDLE;}public void handleEvent(ElevatorEvent event) {switch (currentState) {case IDLE:switch (event) {case CALL_UP:openDoors();currentState = ElevatorState.OPEN_DOORS;break;case CALL_DOWN:// Similar logic for CALL_DOWNbreak;// Handle other events}break;case MOVING_UP:switch (event) {case MOVE_UP:// Logic for moving upbreak;case TIMEOUT:currentState = ElevatorState.IDLE;break;// Handle other events}break;// Implement logic for other states}}private void openDoors() {// Logic to open elevator doorsSystem.out.println("Doors are opening.");}// Define other methods such as closeDoors(), moveUp(), moveDown(), etc.
}

3.使用控制類響應事件

public class ElevatorSystem {public static void main(String[] args) {ElevatorControl elevator = new ElevatorControl();// Simulate eventselevator.handleEvent(ElevatorEvent.CALL_UP);elevator.handleEvent(ElevatorEvent.DOORS_CLOSE);elevator.handleEvent(ElevatorEvent.MOVE_UP);// Add more events as needed}
}

UML 軟件的實現視圖建模

實現視圖

實現視圖是對系統的實現結構建模,包括如下模型圖:

  • 構件圖:建模構件和構件間的接口和依賴關系,表示系統構件組成結構;:
  • 部署圖:建模在系統運行時,構件在系統各節點上的物理部署關系及其運行環境;
  • 子系統與包圖:子系統可以用包來體現,可使用包圖表示系統邏輯架構。

構件圖

  • 構件圖是用來表示系統中構件與構件之間、構件與接口之間關系的圖。
  • 構件圖可以從多種層次粒度描述系統實現架構,如系統分解哪幾個子系統,子系統包括哪些構件,構件由哪些類封裝組成。

構件和構件之間的依賴關系

image-20231223181134347

構件與接口之間的關系

  • 構件與構件之間通過定義良好的接口進行協作。
  • 構件圖中,構件之間的關系表現為依賴關系實現關系
  • 實現關系指一個構件實現了一個接口,使用實線連接到小圓上。該接口被稱為供給接口
  • 依賴關系指一個構件使用了一個接口,使用實線連接到半圓上。該接口被稱為請求接口

image-20231223181425907

端口

端口是指構件一個對外交互點。端口顯示為一個小正方形,放置在構件方框的邊界上。

image-20231223181609946

端口連接

在 UML 軟件架構建模設計中,主要使用如下連接器將構件的端口進行連接。

  • 裝配連接器:用于連接構件之間的端口
  • 委托連接器:用于連接構件供給端口與內部供給端口或內部請求端口與構件請求端口

image-20231223182203179

作為一種選擇, UML 還允許將連接器按如下方案連接構件端口。

image-20231223182641103

若有多個構件使用相同接口訪問另一構件接口, UML 允許將連接器按如下方案連接構件端口。

image-20231223184949103

身份認證構件 (Authentication)端口與訂單構件 (Orders) 端口均使用相同請求接口(lCustomers)連接客戶構件(:Customers )端口的供給接口lCustomers。

委托連接器是將構件的端口連接到實現該行為的對象。它表示消息到達一個端口后,將被傳遞給內部目標對象進行處理。

image-20231223185338266

image-20231223185434470

案例:電子商務系統的構件圖

image-20231223185547292

部署圖

  • 部署圖用于對系統的物理實現情況進行建模。
  • 部署圖用于表示軟件構件如何部署到硬件環境中,它顯示系統中的不同構件在何處物理地運行,以及彼此之間如何進行通信。

節點

  • 節點是指人工制品和構件在系統中部署的硬件設備及其運行環境。
  • 節點之間通過通信線路將連接起來實現信息傳輸。

image-20231223190533597

構件在節點中部署

構件需要在節點設備中運行。在建模時,需要將構件在節點中進行部署

image-20231223190606027

案例:電子商務系統部署圖

image-20231223190641805

包圖

  • 在 UML 模型圖中包用來對模型元素進行分組,簡化 UML 圖,使其更容易理解。
  • 包圖用于對模型自身組織進行建模,它是由一系列模型元素(類、用例等)構成的包所組成的模型,描述包與包之間的關系。

UML 中包表示為左上方帶有小矩形的矩形。包的名稱采用字符串,簡單名僅包含名稱字符串,全限定名則以本包所處的外圍包的名稱作為前綴。

image-20231223191018148

包的可見性

包可以控制protected所包含的內部元素的可見性,即外部元素訪問包內元素的權限:

  • + public公共可見性: 對它所在包和內嵌包的對象可見,也對所有引入它的包及其子包中對象可見;
  • - private私有可見性: 只對它所在包中對象可見;
  • # protected保護可見性: 對它所在包和內嵌包中對象可見;

image-20231223191331202

包的嵌套

  • 包可以擁有其他包,子包又可以擁有自己的子包,從而構成嵌套結構。
  • 包的嵌套可以清晰地表現模型元素之間的層次結構關系。
  • 但是包的嵌套不宜過深,層數一般以 2到 3 層為宜

image-20231223191441457

包圖

  • 包圖描述包與包之間的關系,可用于描述軟件系統的邏輯模型。
  • 包與包之間可以存在依賴關系。兩個包之間存在著依賴關系通常是指這兩個包所包含的模型元素之間存在著一個或多個依賴關系。
  • 包的依賴關系使用一根虛線箭線表示,箭頭指向被依賴的包。依賴關系可以標上標簽,在《》中包含依賴關系的類型。

image-20231223191748930

案例:應用包圖描述系統的軟件架構

image-20231223191823052

image-20231223191939764

針對如下股票投資分析系統構件模型,分析構件之間關系如何設計?

image.png

ChatGPT4:

在這個股票投資分析系統的構件模型中,構件之間的關系是按照客戶端-服務器架構設計的。客戶端包含用戶界面(GUI)、圖形庫(Graphing Lib)、客戶端會話(Client Session)和股票組合(Stock Portfolio)構件。服務器端包含認證服務器(Authentication Server)、服務器會話(Server Session)、股票市場分析器(Stock Market Analyzer)和投資組合數據庫(Portfolio DB)構件。

客戶端的GUI用于展示信息和接收用戶輸入,圖形庫用于數據可視化。客戶端會話管理用戶與系統的交互,而股票組合構件負責管理用戶的個人投資組合信息。這些客戶端構件通過API與服務器端的構件交互。服務器端的認證服務器負責處理登錄和安全認證,服務器會話維護與客戶端的連接狀態。股票市場分析器是系統的核心,負責分析股票市場數據和生成投資建議,而投資組合數據庫存儲用戶的投資組合信息。

客戶端與服務器之間的交互通過網絡進行。例如,用戶通過GUI發起請求,客戶端會話將請求發送到服務器,服務器會話接收請求并與認證服務器進行認證,然后由股票市場分析器處理請求。結果通過服務器會話返回給客戶端會話,并最終通過GUI展示給用戶。

此外,系統還接入了第三方服務,如彭博數據庫(Bloomberg DB),這提供了額外的市場數據,股票市場分析器可能會使用這些數據來增強分析結果的準確性。

針對如下房地產按揭交易系統部署模型,分析各要素之間關系如何設計?

image.png

針對如下電商系統軟件架構模型,分析包之間關系如何設計?

image.png

《use》關系表示使用依賴,Web Shopping依賴Payment,Mobile Shopping依賴Payment…

《merge》關系表示合并,Web Shopping、Mobile Shopping、Phone Shopping、和Mail Shopping合并之后就擁有了Shopping Cart的全部功能 。也表明了它們共享一些在“Web Shopping”包中定義的通用功能。

《Access》關系表示私有引入,比如代碼中的指定包名類名 。Payment可以訪問Shopping Cart中的特定功能或類,但這種訪問是受限的。

《Import》關系表示公共引入,比如Java中的import之后,就可以直接使用import包中的類了。一旦“Shopping Cart”公共導入了“Inventory”,它就可以直接使用“Inventory”中定義的公共類和接口。

圖書借閱管理系統軟件建模設計實踐

系統需求

image-20231223200450359

image-20231223200521472

image-20231223200634562

系統靜態模型設計

建立系統靜態模型類圖。建立類圖需要確定系統中的類,確定類的屬性,確疋類之間的關系。根據系統動態模型確定類的操作并完善類圖。

( 1 )確定系統中的類

  • 系統用戶有管理員 (Administrator) 、圖書管理員 (Librarian) 和借閱者(Borrower) 三個參與者,可將他們抽取為的角色實體類。
  • 系統需存儲圖書信息,可抽取出Book類;需要存儲借閱信息,可抽取出Loan類;需要存儲預定信息,可抽取出Reservation類;這些類是系統中的主要業務實體類。

( 2 )確定類的屬性

image-20231223200936822

( 3 )確定類之間的關系,創建系統類圖

image-20231223201018670

系統動態模型設計

系統詳細設計階段,針對用例圖中的每一個用例,考慮如何通過對象之間的協作來完成用例的功能。采用順序圖或通信圖對用例功能進行設計建模,采用狀態機圖對類的行為狀態進行設計建模。

圖書搜索功能邏輯設計

image-20231223201152550

image-20231223201207722

圖書借閱功能邏輯設計

image-20231223201319348

圖書歸還功能邏輯設計

image-20231223201354929

Book對象的狀態機圖設計

Book 對象是圖書管理系統中具有明顯狀態變化的對象,圖書借閱業務都與Book對象狀態有關。Book對象具有如下狀態: 新書 (NewBook) 、可借閱預定(Available) 、被預定 (Reserved) 、被借閱 (Borrowed) 、被刪除 (Deleted)。

image-20231223201509834

Borrower對象的狀態機圖設計

Borrower對象也具有比較明顯的狀態,因此也采用狀態機圖對其建模。

Borrower 對象具 有 如下狀態: 新建 (NewUser) 、未預定未借書 (NoLoanReserve) 、有預定 (HasReserve) 、有借書 (HasLoan) 、有預定有借書 (HasLoanReserve) 、被刪除 (Deleted)。

image-20231223201645185

靜態結構的類圖模型細化設計

  • Borrower類需要提供

    • checkBorrower操作
    • checkNumBooks操作
    • addLoan操作
    • deleteLoan操作
  • Book類需要提供

    • searchBook操作
    • checkBook操作
    • setLoanStatus操作
  • Loan類需要提供

    • addLoan操作
    • deleteLoan操作
    • checkOverdue操作

image-20231223201905272

針對圖書借閱管理系統如下構件,如何設計系統部署圖模型,并在部署圖中給出部署關系和運行環境(Apache、JBoss、PostgreSQL、Ubuntu)。

1)頁面構件:borrowBook.jsp、returnBook.jsp、reserveBook.jsp、searchBook.jsp、viewBook.jsp、borrowerInfo.jsp,

2)控制構件:borrowBook.java、returnBook.java、reserveBook.java、searchBook.java、viewBook.java、borrowerInfo.java,

3)實體構件:book.java、reservation.java、loan.java、borrower.java,

4)數據庫表:BookInfo、Reservation、Loan、Borrower、BookType

ChatGPT4:

我們可以按照三層架構來組織這些構件:

  • 表示層(通過Apache和JBoss托管): 包括所有的JSP頁面,如 borrowBook.jsp, returnBook.jsp 等。
  • 業務邏輯層(運行在JBoss上): 包括控制和實體構件,如 borrowBook.java, book.java 等。
  • 數據層(使用PostgreSQL): 包含所有數據庫表,如 BookInfo, Loan 等。

現在,我將詳細設計一個系統部署圖模型來展示這些構件是如何部署和相互作用的:

  1. Apache Web Server: 托管所有的JSP頁面。這些頁面通過HTTP請求與JBoss服務器通信。
  2. JBoss Application Server: 處理來自Apache服務器的請求,并運行Java控制和實體構件。JBoss可以部署這些Java構件,并提供必要的運行環境。
  3. PostgreSQL Database Server: 存儲所有的數據庫表,由JBoss服務器通過JDBC進行訪問和操作。
  • Apache Web Server托管JSP頁面,并將請求轉發給JBoss服務器。
  • JBoss服務器處理業務邏輯,并與數據庫服務器進行交互以存儲或檢索數據。
  • PostgreSQL數據庫服務器存儲和管理數據,為業務邏輯層提供數據支持。

所有這些組件都部署在Ubuntu操作系統上,確保系統兼容性和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450426.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

YAML文件解析

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 YAML是“另一種標記語言”的外語縮寫,YAML 是一種比JSON&#xff08;json多層次{ 與 [ 會被搞暈的&#xff09;更直觀的表現形式&#xf…

120分鐘React快速掃盲教程

在教程開端先說些題外話&#xff0c;我喜歡在學習一門新技術或讀過一本書后&#xff0c;寫一篇教程或總結&#xff0c;既能幫助消化&#xff0c;也能加深印象和發現自己未注意的細節&#xff0c;寫的過程其實仍然是一個學習的過程。有個記錄的話&#xff0c;在未來需要用到相關…

springmvc知識點

一、SpringMVC概述 Spring MVC 是由Spring官方提供的基于MVC設計理念的web框架。 SpringMVC是基于Servlet封裝的用于實現MVC控制的框架&#xff0c;實現前端和服務端的交互。 1.1 SpringMVC優勢 嚴格遵守了MVC分層思想 采用了松耦合、插件式結構&#xff1b;相比較于我們封裝的…

spring @component的作用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1、controller 控制器&#xff08;注入服務&#xff09; 2、service 服務&#xff08;注入dao&#xff09; 3、repository dao&#xff…

微信小程序 懸浮按鈕

2019獨角獸企業重金招聘Python工程師標準>>> 效果視頻 https://pan.baidu.com/s/1yfrDaG9YAX0--v0EA3awZA 布局需要按照圓形排列&#xff0c;所以我們需要計算每個點的坐標 代碼部分 <view styleposition:fixed; wx:for"{{list}}" wx:for-index"i…

C語言const關鍵字—也許該被替換為readolny

const 是constant 的縮寫&#xff0c;是恒定不變的意思&#xff0c;也翻譯為常量、常數等。很不幸&#xff0c;正是因為這一點&#xff0c;很多人都認為被const 修飾的值是常量。這是不精確的&#xff0c;精確的說應該是只讀的變量&#xff0c;其值在編譯時不能被使用&#xff…

dbus服務自啟動方法

Linux 一般發行版上 "/usr/share/dbus-1/services/"目錄就是dbus放service文件的地方。 需要自動啟動的服務器 就在這個目錄放一個 service文件&#xff0c;內容如下&#xff1a; $ cat /usr/share/dbus-1/services/dhcdbd.service [D-BUS Service] Namecom.redhat.…

在Spring Boot中使用 @ConfigurationProperties 注解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 上一篇博客寫了 如何在Spring Boot application中配置mail . 使用 Value 注解注入屬性. 但 Spring Boot 提供了另一種方式 &#xff0c;能…

Micronaut教程:如何使用基于JVM的框架構建微服務

\本文要點\\Micronaut是一種基于jvm的現代化全棧框架&#xff0c;用于構建模塊化且易于測試的微服務應用程序。\\tMicronaut提供完全的編譯時、反射無關的依賴注入和AOP。\\t該框架的開發團隊和Grails框架的開發團隊是同一個。\\tMicronaut框架集成了云技術&#xff0c;服務發現…

C語言extern關鍵詞—最會帶帽子的關鍵字

extern&#xff0c;外面的、外來的意思。那它有什么作用呢&#xff1f;舉個例子&#xff1a;假設你在大街上看到一個黑皮膚綠眼睛紅頭發的美女&#xff08;外星人&#xff1f;&#xff09;或者帥哥。你的第一反應就是這人不是國產的。extern 就相當于他們的這些區別于中國人的特…

解決Coldfusion連接MySQL數據庫的問題

在連接MySQL時&#xff0c;出現了如下錯誤&#xff1a; Connections to MySQL Community Server are not supported. Please contact MySQL to obtain a MySQL Enterprise or Commercial version. 解決方案&#xff1a; step 1: download the JDBC driver JDBC Driver for MySQ…

范式知識點

Mysql數據庫 ?前關系數據庫有六種范式&#xff1a; 第?范式&#xff08;1NF&#xff09;、第?范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;、巴斯-科德范式 &#xff08;BCNF&#xff09;、第四范式(4NF&#xff09;和第五范式&#xff08;5NF&a…

Tensorflow入門----占位符、常量和Session

安裝好TensorFlow之后&#xff0c;開一個python環境&#xff0c;就可以開始運行和使用TensorFlow了。 先給一個實例&#xff0c; #先導入TensorFlowimport tensorflow as tf # Create TensorFlow object called hello_constanthello_constant tf.constant(Hello World!) with …

C語言union關鍵字

union 關鍵字的用法與struct 的用法非常類似。union 維護足夠的空間來置放多個數據成員中的“一種”&#xff0c;而不是為每一個數據成員配置空間&#xff0c;在union 中所有的數據成員共用一個空間&#xff0c;同一時間只能儲存其中一個數據成員&#xff0c;所有的數據成員具有…

js 深拷貝 和 淺拷貝

1、 ...運算符 &#xff08;淺拷貝&#xff09; let obj {a:1,b:2}; let obj2 {...obj}; obj.a3 obj //{a: 3, b: 2} obj2 //{a: 1, b: 2}a {a:[{b:1}]}; b a ;b.a[0].b 2; //b {a:[{b:2}]}a // a {a:[{b:2}]} 2、 JSON.parse(JSON.stringify(參數))…

軟考如何備考

軟考上半年 報名時間 3月 考試時間 5月 備考持續時間&#xff1a;一個半月&#xff0c;每天至少兩個小時。 第一輪 基礎知識輪&#xff0c; 15天 在這一輪中如果碰到無法理解的知識點一定不要過于糾結&#xff0c;往后學&#xff0c;一般后面的學著學著之前的內容就…

Python學習第一天-第2節

*本節課內容參見&#xff1a;https://www.cnblogs.com/jin-xin/articles/7459977.html運行第一個Python程序 print(hello world) 將文本文件保存為以.py結尾的文件&#xff0c;如hello_world.py &#xff0c;在終端中&#xff0c;運行命令&#xff1a;Python hello_world.py&am…

SpringMVC之組合注解@GetMapping

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Spring4.3中引進了&#xff5b;GetMapping、PostMapping、PutMapping、DeleteMapping、PatchMapping&#xff5d;&#xff0c;來幫助簡化…

資源下載地址

1、nginx http://nginx.org/en/download.html 2、nodejs http://nodejs.cn/download/ 3、vscode https://code.visualstudio.com/ 4、canal https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deployer-1.1.4.tar.gz 5、jenkins https://jenkins.io/i…

C語言volatile關鍵字—最易變的關鍵字

volatile 是易變的、不穩定的意思。很多人根本就沒見過這個關鍵字&#xff0c;不知道它的存在。也有很多程序員知道它的存在&#xff0c;但從來沒用過它。我對它有種“楊家有女初長成,養在深閨人未識” 的感覺。volatile 關鍵字和const 一樣是一種類型修飾符&#xff0c;用它修…