<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 開閉原則 > 原文: [https://howtodoinjava.com/design-patterns/open-closed-principle/](https://howtodoinjava.com/design-patterns/open-closed-principle/) **開閉原則**(OCP)指出,模塊應該可以擴展,但可以關閉以進行修改。 它是著名的 5 條[實體原則](https://howtodoinjava.com/best-practices/5-class-design-principles-solid-in-java/)和非常重要的*面向對象設計原則*之一。 ## 1.開閉原則的定義 有兩種流行的定義來描述這一原則: #### 1.1 Mayer 的定義 伯特蘭·梅耶(Bertrand Mayer)在其 1988 年的著作面向對象的軟件構造(Prentice Hall)中,定義了開閉原則(OCP)如下: > 軟件實體應為擴展而開放,但應為修改而封閉。 #### 1.2 Martin 的定義 Robert C. Martin 在他的書《敏捷軟件開發:原則,模式和實踐》(Prentice Hall,2003 年)中定義了 OCP,如下所示: **開放擴展** – 這意味著可以擴展模塊的行為。 隨著應用需求的變化,我們能夠通過滿足這些變化的新行為來擴展模塊。 換句話說,我們能夠更改模塊的功能。 **封閉修改** – 擴展模塊的行為不會導致模塊的源代碼或二進制代碼更改。 模塊的二進制可執行版本,無論是在可鏈接庫,DLL 還是 Java .jar 中,都保持不變。 ## 2.討論 根據上面引用的定義,對于要開放擴展的代碼,開發人員必須能夠響應不斷變化的需求并支持新功能。 盡管模塊無法修改,但仍必須做到這一點。 開發人員必須支持新功能,而無需編輯源代碼或現有模塊的已編譯程序集。 #### 2.1 例外情況 請注意,在少數情況下,絕對有必要修改代碼,并且無法避免。 * 這樣的例子之一就是模塊中存在的缺陷。 在修復缺陷的情況下,允許更改模塊代碼及其相應的測試用例。 我們可以使用 [TDD](https://en.wikipedia.org/wiki/Test-driven_development) 方法來解決代碼中的這些問題。 修正錯誤后,您必須確保沒有其他測試會因副作用而失敗。 * 另一個允許的例外情況是,允許對現有代碼進行任何更改,只要它也不需要更改該代碼的任何客戶端即可。 這允許使用新的語言功能升級模塊版本。 例如,[Spring 5](https://howtodoinjava.com/spring-5-tutorial/) 支持并使用 [Java8 lambda](https://howtodoinjava.com/java-8-tutorial/) 語法,但要使用它,我們不需要更改我們的客戶端應用代碼。 一個模塊,其中的類是松散耦合的,在不強迫其他類更改的情況下更改了類,這就是鼓勵松散耦合的原因。 如果您允許對現有代碼進行修改而不會強制對客戶端進行進一步更改,則保持松散的耦合將限制 OCP 的影響。 #### 2.2 如何設計開閉原則 為了實現模塊的擴展,我們可以采用兩種(通常使用的)機制中的任何一種。 ###### 2.2.1 實現繼承 實現繼承使用[**抽象類和方法**](https://howtodoinjava.com/java/basics/abstract-keyword/)。 您可以將擴展點定義為抽象方法。 該抽象類可以由幾個具有大多數常見場景的預定義實現的類擴展。 對于特定于客戶的場景,開發人員必須擴展抽象類并提供特定的實現邏輯。 這將有助于保留 OCP。 [**模板方法模式**](https://howtodoinjava.com/design-patterns/behavioral/template-method-pattern/)非常適合這些用例。 在這種模式下,由于可以委托抽象方法,因此可以自定義一般步驟。 實際上,基類將流程的各個步驟委托給子類。 ###### 2.2.2 接口繼承 在[接口](https://howtodoinjava.com/oops/exploring-interfaces-and-abstract-classes-in-java/)繼承中,客戶端對類的依賴關系被替換為接口。 與抽象方法相比,這實際上是首選方法。 這呼應了這樣的建議,即首選組合而不是[繼承](https://howtodoinjava.com/oops/java-inheritance/),并保持繼承層次結構較淺,并且子分類層很少。 > 設計繼承或禁止繼承。 – Effective Java(Addison-Wesley,2008 年),約書亞·布洛赫(Joshua Bloch) ## 3.開閉原則示例 如果要查看**開閉原則的真實示例**,只需看一下 **Spring 框架**即可。 Spring 的設計和實現非常精美,因此您可以擴展其功能的任何部分,并立即將自定義實現注入。 它經過了很好的時間測試,并且像今天一樣完美無缺。 #### 3.1 沒有 OCP 的計算器程序 假設我們正在創建一個簡單的計算器模塊,其中僅包含兩個加減運算。 該模塊的代碼如下。 ```java public interface IOperation { } ``` ```java public class Addition implements IOperation { private double firstOperand; private double secondOperand; private double result = 0.0; public Addition(double firstOperand, double secondOperand) { this.firstOperand = firstOperand; this.secondOperand = secondOperand; } //Setters and getters } ``` ```java public class Substraction implements IOperation { private double firstOperand; private double secondOperand; private double result = 0.0; public Substraction(double firstOperand, double secondOperand) { this.firstOperand = firstOperand; this.secondOperand = secondOperand; } //Setters and getters } ``` ```java public interface ICalculator { void calculate(IOperation operation); } ``` ```java public class SimpleCalculator implements ICalculator { @Override public void calculate(IOperation operation) { if(operation == null) { throw new InvalidParameterException("Some message"); } if(operation instanceof Addition) { Addition obj = (Addition) operation; obj.setResult(obj.getFirstOperand() + obj.getSecondOperand()); } else if(operation instanceof Substraction) { Addition obj = (Addition) operation; obj.setResult(obj.getFirstOperand() - obj.getSecondOperand()); } } } ``` 上面的模塊代碼看起來不錯并達到目的。 但是,在客戶端應用中時,開發人員想要增加乘法功能 – 除了更改方法`calculate()`中的`SimpleCalculator`類代碼外,他別無選擇。 此代碼不符合 OCP。 #### 3.2 符合 OCP 的代碼 請記住,抽象功能是應用中的變化。 在此計算器程序中,`calculate`方法中的代碼將隨每個傳入的新操作支持請求而變化。 因此,我們需要在此方法中添加抽象。 解決方案是委派在操作本身內部提供計算邏輯的責任。 每個操作必須具有自己的邏輯才能獲取結果和操作數。 現在查看修改后的代碼。 ```java public interface IOperation { void performOperation(); } ``` ```java public class Addition implements IOperation { private double firstOperand; private double secondOperand; private double result = 0.0; public Addition(double firstOperand, double secondOperand) { this.firstOperand = firstOperand; this.secondOperand = secondOperand; } //Setters and getters @Override public void performOperation() { result = firstOperand + secondOperand; } } ``` ```java public class Substraction implements IOperation { private double firstOperand; private double secondOperand; private double result = 0.0; public Substraction(double firstOperand, double secondOperand) { this.firstOperand = firstOperand; this.secondOperand = secondOperand; } //Setters and getters @Override public void performOperation() { result = firstOperand - secondOperand; } } ``` ```java public interface ICalculator { void calculate(IOperation operation); } ``` ```java public class SimpleCalculator implements ICalculator { @Override public void calculate(IOperation operation) { if(operation == null) { throw new InvalidParameterException("Some message"); } operation.performOperation(); } } ``` 現在,我們可以根據需要添加任意數量的操作,而無需更改原始模塊代碼。 任何新的操作都將輕松實現。 例如,乘法運算將這樣寫,并且可以正常工作。 ```java public class Multiplication implements IOperation { private double firstOperand; private double secondOperand; private double result = 0.0; public Multiplication(double firstOperand, double secondOperand) { this.firstOperand = firstOperand; this.secondOperand = secondOperand; } //Setters and getters @Override public void performOperation() { result = firstOperand * secondOperand; } } ``` ## 4\. 結論 **開閉原則**是類和接口的總體設計以及開發人員如何構建允許隨時間變化的代碼的指南。 現在,當大多數組織都在采用[敏捷實踐](https://en.wikipedia.org/wiki/Agile_software_development)時,每次經過 sprint 時,新的需求都是不可避免的,應該被接受。 如果您生成的代碼不是為了進行更改而構建的,則更改將很困難,耗時,容易出錯且成本很高。 通過確保代碼可以擴展但不能修改,可以有效地禁止將來對現有類和程序集進行更改,這迫使程序員創建可以插入擴展點的新類。 建議的方法是確定需求中可能更改的部分或難以實現的部分,并將這些部分排除在擴展點之后。 學習愉快! 閱讀更多: [維基百科](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看