設計模式之開閉原則:對修改關閉,對擴充套件開放

tenor發表於2019-02-16
  • 底層模組的變更,必然有高層模組的耦合,開閉原則就是減少變更的擴充套件性

通俗的意思就是說,在開發過程中,在前期設計就必須做好相對應的擴充套件

  • 在修改程式碼時必須要儘量少動原有的程式碼,最好不要修改老的程式碼,這就是對修改關閉
  • 那麼如何處理新的需求呢?這裡就涉及到程式碼的前期涉及了,儘量做到的是新增函式,只對新需求做擴充套件

這裡舉一個栗子:

這裡有個表單:

<div id="loginForm">
    <input type="text" class="username" id="username" placeholder="username"><br>
    <input type="text" class="pwd" id="pwd" placeholder="pwd"><br>
    <button onclick="checkLogin()">提交</button>
</div>
複製程式碼

一般做前端校驗的方法可能就會是這個樣子:

  • 寫一個公共的校驗方法來對錶單中的每個輸入項進行校驗
  • 取出 input 表單中的每個值,依次根據指定的校驗規則,來校驗前端輸入的內容
  • 如果出現錯誤的話,就會對這個輸入錯誤的資料進行提醒

比如下面這樣的方式:

function checkLogin() {

    let username = document.querySelector("#username").value;
    if (!username) {
        alert("username must not be null");
    }

    let pwd = document.querySelector("#pwd").value;
    if (!pwd) {
        alert("pwd must not be null");
    }
}
複製程式碼

這樣就會面臨下面的問題:

  • 如果校驗規則有變動的話,就需要對原來的程式碼進行修改
  • 如果需求有變動,比如在原來的表單中新增了一個 input 輸入框的話,就還需要修改原來的這個校驗的程式碼
  • 一般來說,修改程式碼都有可能對原來的程式碼造成一定的問題,修改就有可能出錯

對修改關閉

這是一個非常重要的原則,對原來已有的程式碼最好不做修改

那麼我們在這裡該這麼做呢?看這樣的修改:

  1. 在 html 中新增一個 input 輸入框自身的自定義屬性 data-validate 用來標識這個 input 輸入框對應的校驗函式名
<div id="loginForm">
    <input type="text" class="username" data-validate="checkUsername" id="username" placeholder="username"><br>
    <input type="text" class="pwd" data-validate="checkPwd" id="pwd" placeholder="pwd"><br>
    <button onclick="checkLoginForm()">提交</button>
</div>
複製程式碼
  1. 寫通用函式,專門負責這個表單的校驗,獲取所有的 input 輸入框,拿到對應的校驗函式,並呼叫對應的掛載在 window 上的校驗函式
function checkLoginForm() {
    // 表單
    let form = document.querySelector("#loginForm");
    // 表單中input
    let ipts = form.querySelectorAll("input");
    // 獲取input中的校驗函式名,並呼叫對應的函式
    for (let i = 0; i < ipts.length; i++) {
        let input = ipts[i];
        let validate = input.dataset.validate;
        let validateFn = window[validate];
        if (validateFn) {
            let rst = !validateFn(input.value);
            if (rst) {
                return false;
            }
        } else {
            alert(`當前沒有這個${validate}校驗函式`);
        }
    }

}
複製程式碼
  1. 這樣以後的擴充套件就可以單獨寫對應的校驗函式就ok,無需再去修改原來的 checkLoginForm 函式,同時校驗函式還可以複用。
function checkUsername(username) {
    if (!username) {
        alert("username must not be null");
    }
}
複製程式碼
  1. data-validate="checkUsername" 屬性值對應的就是通用的校驗函式名稱,減少對原有程式碼的修改和侵入。

相關文章