<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智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                第15章 命令模式 15.1 項目經理也難當 我是公司的項目經理,在國內做項目,項目經理需要什么都懂,什么都管。做好了,項目經理能分到一杯羹;做不好,都是項目經理的責任。這幾乎是絕對的,我帶過很多項目,行政命令一壓下來,那就一條道:做完做好! 雖然我們公司是一個集團公司,但是我們部門的業績是獨立核算的,也就是說,我們部門不僅可以為集團公司服務,還可以為其他甲方服務,賺取更多的外快。2007年,我曾負責一個比較小的項目(但是項目的合同金額可不少)——為某家旅行社建立一套內部管理系統。該旅行社的門店比較多,員工也比較多,這個內部管理系統用來管理客戶、旅游資源、票務以及內部事務,整體上類似于一個小型的MIS系統。客戶的需求比較明確,因為他們曾經自己購買了一套內部管理系統,這次變動基本上是翻版;而且這家旅行社也有自己的IT部門,技術人員之間語言相通,比較好相處,也沒有交流鴻溝。 該項目的成員分工采用了常規的分工方式,分為需求組(Requirement Group,RG)、美工組(Page Group,PG)、代碼組(我們內部還有一個比較優雅的名字:邏輯實現組,這里使用大家經常稱呼的名稱,即Code Group,簡稱CG),加上我這個項目經理正好十個人。剛開始,客戶(也就是旅行社,甲方)很樂意和我們每個組探討,比如和需求組討論需求、和美工討論頁面、和代碼組討論實現,告訴他們修改、刪除、增加各種內容等。這是一種比較常見的甲乙方合作模式,甲方深入到乙方的項目開發中,我們可以使用類圖來表示這個過程,如圖15-1所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036435510.jpg) 圖15-1 旅行社項目開發過程類圖 這個類圖很簡單,客戶和三個組都有交流,這也合情合理。那我們看看這個過程的實現,首先看抽象類Group,如代碼清單15-1所示。 代碼清單15-1 抽象組 public?abstract?class?Group?{ ?????//甲乙雙方分開辦公,如果你要和某個組討論,你首先要找到這個組 ?????public?abstract?void?find(); ?????//被要求增加功能 ?????public?abstract?void?add(); ?????//被要求刪除功能 ?????public?abstract?void?delete(); ?????//被要求修改功能 ?????public?abstract?void?change(); ?????//被要求給出所有的變更計劃 ?????public?abstract?void?plan(); } 大家看抽象類中的每個方法,其中的每個都是一個命令語氣——“找到它,增加,刪除,給我計劃!”這些都是命令,給出命令然后由相關的人員去執行。我們再看3個實現類,其中的需求組最重要,需求組RequirmentGroup類如代碼清單15-2所示。 代碼清單15-2 需求組 public?class?RequirementGroup?extends?Group?{ ?????//客戶要求需求組過去和他們談 ?????public?void?find()?{ ?????????????System.out.println("找到需求組..."); ?????} ?????//客戶要求增加一項需求 ?????public?void?add()?{ ?????????????System.out.println("客戶要求增加一項需求..."); ?????} ?????//客戶要求修改一項需求 ?????public?void?change()?{ ?????????????System.out.println("客戶要求修改一項需求..."); ?????} ?????//客戶要求刪除一項需求 ?????public?void?delete()?{ ?????????????System.out.println("客戶要求刪除一項需求..."); ?????} ?????//客戶要求給出變更計劃 ?????public?void?plan()?{ ?????????????System.out.println("客戶要求需求變更計劃..."); ?????} } 需求組有了,我們再看美工組。美工組也很重要,是項目的臉面,客戶最終接觸到的還是界面。美工組PageGroup類如代碼清單15-3所示。 代碼清單15-3 美工組 public?class?PageGroup?extends?Group?{????? ?????//首先這個美工組應該能找到吧,要不你跟誰談? ?????public?void?find()?{ ?????????????System.out.println("找到美工組..."); ?????} ?????//美工被要求增加一個頁面 ?????public?void?add()?{ ?????????????System.out.println("客戶要求增加一個頁面..."); ?????} ?????//客戶要求對現有界面做修改 ?????public?void?change()?{ ?????????????System.out.println("客戶要求修改一個頁面..."); ?????} ?????//甲方是老大,要求刪除一些頁面 ?????public?void?delete()?{ ?????????????System.out.println("客戶要求刪除一個頁面..."); ?????} ?????//所有的增、刪、改都要給出計劃 ?????public?void?plan()?{ ?????????????System.out.println("客戶要求頁面變更計劃..."); ?????} } 最后看代碼組。這個組的成員一般比較沉悶,不多說話,但多做事兒,這是這個組的典型特點。代碼組CodeGroup類如代碼清單15-4所示。 代碼清單15-4 代碼組 public?class?CodeGroup?extends?Group?{ ?????//客戶要求代碼組過去和他們談 ?????public?void?find()?{ ?????????????System.out.println("找到代碼組..."); ?????} ?????//客戶要求增加一項功能 ?????public?void?add()?{ ?????????????System.out.println("客戶要求增加一項功能..."); ?????} ?????//客戶要求修改一項功能 ?????public?void?change()?{ ?????????????System.out.println("客戶要求修改一項功能..."); ?????} ?????//客戶要求刪除一項功能 ?????public?void?delete()?{ ?????????????System.out.println("客戶要求刪除一項功能..."); ?????} ?????//客戶要求給出變更計劃 ?????public?void?plan()?{ ?????????????System.out.println("客戶要求代碼變更計劃..."); ?????} } 整個項目的3個支柱都已經產生了,那看客戶怎么和我們談。客戶剛開始提交了他們自己寫的一份比較完整的需求,需求組根據這份需求寫了一份分析說明書,客戶看后,要求增加需求,該場景如代碼清單15-5所示。 代碼清單15-5 場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//首先客戶找到需求組說,過來談需求,并修改 ?????????????System.out.println("-----------客戶要求增加一項需求---------------"); ?????????????Group?rg?=?new?RequirementGroup(); ?????????????//找到需求組 ?????????????rg.find(); ?????????????//增加一個需求 ?????????????rg.add(); ?????????????//要求變更計劃 ?????????????rg.plan(); ?????} } 運行的結果如下所示: -------------客戶要求增加一項需求----------------- 找到需求組... 客戶要求增加一項需求... 客戶要求需求變更計劃... 客戶的需求暫時滿足了,過了一段時間,客戶又要求“界面多畫了一個,過來談談”,于是又有一次場景變化,如代碼清單15-6所示。 代碼清單15-6 變化的場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//首先客戶找到美工組說,過來談頁面,并修改 ?????????????System.out.println("----------客戶要求刪除一個頁面--------------"); ?????????????Group?pg?=?new?PageGroup(); ?????????????//找到需求組 ?????????????pg.find(); ?????????????//刪除一項需求 ?????????????pg.delete(); ?????????????//要求變更計劃 ?????????????pg.plan(); ?????} } 運行結果如下所示: -------------客戶要求刪除一個頁面----------------- 找到美工組... 客戶要求刪除一個頁面... 客戶要求頁面變更計劃... 好了,界面也談過了,應該沒什么大問題了吧。過了一天后,客戶又讓代碼組過去,說是數據庫設計問題,然后又叫美工組過去,布置了一堆命令……這個就不一一寫了,大家應該能夠體會得到!問題來了,我們修改可以,但是每次都是叫一個組去,布置個任務,然后出計劃,每次都這樣,如果讓你當甲方,你煩不煩?而且這種方式很容易出錯誤,并且還真發生過。客戶把美工叫過去了,要刪除,可美工說需求是這么寫的,然后客戶又命令需求組過去,一次次地折騰之后,客戶也煩躁了,于是直接抓住我這個項目經理說:“我不管你們內部怎么安排,你就給我找個接頭負責人,我告訴他怎么做,刪除頁面,增加功能,你們內部怎么處理我不管,我就告訴他我要干什么就成了……” 我一聽,好啊,這也正是我想要的,我們項目組的兄弟們也已經受不了了,于是我改變了一下我的處理方式,如圖15-2所示。 ![](https://box.kancloud.cn/2016-08-14_57b003644a7e5.jpg) 圖15-2 增加負責人后的類圖 在原有的類圖上增加了一個Invoker類,其作用是根據客戶的命令安排不同的組員進行工作,例如,客戶說“界面上刪除一條記錄”,Invoker類接收到該String類型命令后,通知美工組PageGroup開始delete,然后再找到代碼組CodeGroup后臺不要存到數據庫中,最后反饋給客戶一個執行計劃。這是一個挺好的方案,但是客戶的命令是一個String類型的,這有非常多的變化,僅僅通過一個字符串來傳遞命令并不是一個非常好的方案,因為在系統設計中,字符串沒有約束力,根據字符串判斷相關的業務邏輯不是一個優秀的解決方案。那怎么才是一個優秀的方案呢?解決方案是:對客戶發出的命令進行封裝,每個命令是一個對象,避免客戶、負責人、組員之間的交流誤差,封裝后的結果就是客戶只要說一個命令,我的項目組就立刻開始啟動,不用思考、解析命令字符串,如圖15-3所示。 ![](https://box.kancloud.cn/2016-08-14_57b003645fc28.jpg) 圖15-3 完美的類圖 Command抽象類只有一個方法execute,其作用就是執行命令,子類非常堅決地實現該命令,與軍隊中類似,上級軍官給士兵發布命令:爬上這個旗桿!然后士兵回答:Yes,Sir!完美的項目也與此類似,客戶發送一個刪除頁面的命令,接頭負責人Invoker接收到命令后,立刻執行DeletePageCommand的execute方法。對類圖中增加的幾個類說明如下。 ● Command抽象類:客戶發給我們的命令,定義三個工作組的成員變量,供子類使用;定義一個抽象方法execute,由子類來實現。 ● CInvoker實現類:項目接頭負責人,setComand接收客戶發給我們的命令,action方法是執行客戶的命令(方法名寫成是action,與command的execute區分開,避免混淆)。 其中,Command抽象類是整個擴展的核心,其源代碼如代碼清單15-7所示。 代碼清單15-7 抽象命令類 public?abstract?class?Command?{???? ?????//把三個組都定義好,子類可以直接使用 ?????protected?RequirementGroup?rg?=?new?RequirementGroup();??//需求組 ?????protected?PageGroup?pg?=?new?PageGroup();??//美工組 ?????protected?CodeGroup?cg?=?new?CodeGroup();??//代碼組??? ?????//只有一個方法,你要我做什么事情 ?????public?abstract?void?execute(); } 抽象類很簡單,具體的實現類只要實現execute方法就可以了。在一個項目中,需求增加是很常見的,那就把“增加需求”定義為一個命令AddRequirementCommand類,如代碼清單15-8所示。 代碼清單15-8 增加需求的命令 public?class?AddRequirementCommand?extends?Command?{ ?????//執行增加一項需求的命令 ?????public?void?execute()?{ ?????????????//找到需求組 ?????????????super.rg.find(); ?????????????//增加一份需求 ?????????????super.rg.add(); ?????????????//給出計劃 ?????????????super.rg.plan(); ?????} } 頁面變更也是比較頻繁發生的,定義一個刪除頁面的命令 DeletePageCommand類,如代碼清單15-9所示。 代碼清單15-9 刪除頁面的命令 public?class?DeletePageCommand?extends?Command?{ ?????//執行刪除一個頁面的命令 ?????public?void?execute()?{ ?????????????//找到頁面組 ?????????????super.pg.find(); ?????????????//刪除一個頁面 ?????????????super.rg.delete(); ?????????????//給出計劃 ?????????????super.rg.plan(); ?????} } Command抽象類可以有N個子類,如增加一個功能命令(AddFunCommand),刪除一份需求命令(DeleteRequirementCommand)等,這里就不再描述了,只要是由客戶產生、時常性的行為都可以定義為一個命令,其實現類都比較簡單,讀者可以自行擴展。 客戶發送的命令已經確定下來,我們再看負責人Invoker,如代碼清單15-10所示。 代碼清單15-10 負責人 public?class?Invoker?{ ?????//什么命令 ?????private?Command?command; ?????//客戶發出命令 ?????public?void?setCommand(Command?command){ ?????????????this.command?=?command; ?????} ?????//執行客戶的命令 ?????public?void?action(){ ?????????????this.command.execute(); ?????} } 這更簡單了,負責人只要接到客戶的命令,就立刻執行。我們模擬增加一項需求的過程,如代碼清單15-11所示。 代碼清單15-11 增加一項需求 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//定義我們的接頭人 ?????????????Invoker?xiaoSan?=?new?Invoker();??//接頭人就是小三 ?????????????//客戶要求增加一項需求 ?????????????System.out.println("------------客戶要求增加一項需求---------------"); ?????????????//客戶給我們下命令來 ?????????????Command?command?=?new?AddRequirementCommand(); ?????????????//接頭人接收到命令 ?????????????xiaoSan.setCommand(command); ?????????????//接頭人執行命令 ?????????????xiaoSan.action(); ?????} } 運行結果如下所示: -------------客戶要求增加一項需求----------------- 找到需求組... 客戶要求增加一項需求... 客戶要求需求變更計劃... 是不是我們的場景類簡單了很多?客戶只要給命令,我馬上執行。簡單!非常簡單!那我們看看,如果客戶要求刪除一個頁面,我們的修改有多大,如代碼清單15-12所示。 代碼清單15-12 刪除一個頁面 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//定義我們的接頭人 ?????????????Invoker?xiaoSan?=?new?Invoker();??//接頭人就是小三 ?????????????//客戶要求增加一項需求 ?????????????System.out.println("------------客戶要求刪除一個頁面---------------"); ?????????????//客戶給我們下命令來 ?????????????//Command?command?=?new?AddRequirementCommand(); ?????????????Command?command?=?new?DeletePageCommand(); ?????????????//接頭人接收到命令 ?????????????xiaoSan.setCommand(command); ?????????????//接頭人執行命令 ?????????????xiaoSan.action(); ?????} } 運行結果如下所示: -------------客戶要求刪除一個頁面----------------- 找到美工組... 客戶要求刪除一項需求... 客戶要求需求變更計劃... 看到上面用粗體顯示的代碼了嗎?只修改了這么多,是不是很簡單,而且客戶也不用知道到底由誰來修改,高內聚的要求體現出來了,這就是命令模式。
                  <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>

                              哎呀哎呀视频在线观看