熱度已經過了,但還是覺得有必要從架構設計的角度來討論一下此事。並用以往我的經驗來設計一套負載能力更好一些的系統。 先說一下基本的架構思路: 最大限度的避免計算,靜態化 不用資料庫,更新類操作使用APPEND模式的文本文件 流程最短,最好是客戶端訪問的第一臺伺服器就能完成全部工作 善用CDN 客戶端負 ...
一 什麼是設計模式
設計模式是一套反覆使用的代碼設計總結。使用設計模式是為了可重用代碼、保證代碼可靠性、程式的重用性。熟悉設計模式能更容易看懂框架源碼,更好的設計自己的系統。
二 設計模式分類
設計模式分為創建型、結構型和行為型三種模式。
三 設計模式的六大原則
開放封閉原則:儘量通過擴展軟體實體來解決需求變化,而不是通過修改已有的代碼來完成變化
里氏代換原則:使用的基類可以在任何地方使用繼承的子類,完美的替換基類。子類可以擴展父類的功能,但不能改變父類原有的功能。子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法【模版模式的鉤子方法不在此列】,子類中可以增加自己特有的方法
依賴倒轉原則:面向介面編程,我們在程式代碼中傳遞參數時或在關聯關係中,儘量引用層次高的抽象層類
介面隔離原則:使用多個隔離的介面,比使用單個介面要好
迪米特法則:一個類儘量減少自己對其他對象的依賴,簡稱類間解耦
單一職責原則:一個方法只負責一件事情
四 常用的設計模式
4.1 單例模式
使用場景:
網站計數器、應用程式日誌應用、線程池
註意事項:
註意線程安全問題
代碼實現:
1 package com.leo.basic.code.design; 2 3 /** 4 * @DESCRIPTION 5 * 單例模式:採用一定的方式保證一個類在一個系統中只有一個實例 6 * 優點:單例模式保證了系統記憶體中該類只存在一個對象,節省了系統資源,對於一些需要頻繁創建銷毀的對象,使用單例模式可以提高系統性能 7 * 缺點:由於單利模式中沒有抽象層,因此單例類的擴展有很大的困難;不適用於變化的對象 8 * @DATE 2022-11-02 9 * @AUTHOR liuzhilong 10 */ 11 public class SingleTest { 12 13 public static void main(String[] args) { 14 // 1、餓漢式單例模式(靜態常量) 15 Singleton1 singleton1 = Singleton1.getInstance(); 16 Singleton1 singleton2 = Singleton1.getInstance(); 17 System.out.println(singleton1 == singleton2); 18 // 2、餓漢式單例模式(靜態代碼塊) 19 Singleton2 singleton21 = Singleton2.getInstance(); 20 Singleton2 singleton22 = Singleton2.getInstance(); 21 System.out.println(singleton21 == singleton22); 22 // 3、靜態內部類 23 Singleton3 singleton31 = Singleton3.getInstance(); 24 Singleton3 singleton32 = Singleton3.getInstance(); 25 System.out.println(singleton31 == singleton32); 26 } 27 28 29 } 30 // 實現方式 31 // 1、餓漢式單例模式(靜態常量) 32 class Singleton1 { 33 34 private static Singleton1 instance = new Singleton1(); 35 36 private Singleton1() { 37 38 } 39 40 public static Singleton1 getInstance() { 41 return instance; 42 } 43 } 44 45 // 2、餓漢式單例模式(靜態代碼塊) 46 class Singleton2 { 47 48 private static Singleton2 instance; 49 50 static { 51 instance = new Singleton2(); 52 } 53 54 private Singleton2() { 55 56 } 57 58 public static Singleton2 getInstance() { 59 return instance; 60 } 61 } 62 63 // 3、靜態內部類 64 class Singleton3 { 65 66 private Singleton3() { 67 68 } 69 // 採用了類裝載的機制來保證初始化實例時只有一個線程 70 private static class Singleton3Instance{ 71 private static final Singleton3 instance = new Singleton3(); 72 } 73 74 public static Singleton3 getInstance() { 75 return Singleton3Instance.instance; 76 } 77 } 78 79 // 4、枚舉 80 enum Singleton4 { 81 INSTANCE; 82 } 83 84 85 // 5、雙重檢查(Double-check) 86 class Singleton5 { 87 88 private static Singleton5 instance; 89 90 private Singleton5() { 91 92 } 93 // 因為JVM本質重排序的原因,可能會初始化多次,不推薦使用 94 public static Singleton5 getInstance() { 95 if(instance == null){ 96 synchronized (Singleton5.class){ 97 if(instance == null){ 98 instance = new Singleton5(); 99 } 100 } 101 } 102 return instance; 103 } 104 }View Code
4.2 工廠模式
使用場景:
實例化對象、Spring IoC
註意事項:
代碼實現:
1 package com.leo.basic.code.design; 2 3 4 5 /** 6 * @DESCRIPTION 工廠模式: 7 * 簡單工廠:創建對象在工廠類中,工廠類很重【1類產品】 8 * 工廠方法:創建對象在具體工廠實現類中,工廠是個介面【1類產品】 9 * 抽象工廠:工廠中定義了一系列產品創建方法,創建對象在具體的工廠實現類中【多類產品】 10 * 優點:在創建對象時不會對客戶端暴露創建邏輯,實現了創建者和調用者分離 11 * 缺點: 12 * @DATE 2022-11-02 13 * @AUTHOR liuzhilong 14 */ 15 public class FactoryTest { 16 17 public static void main(String[] args) { 18 // 1、簡單工廠 19 Car aodi = SimpleCarFactory.createCar("奧迪"); 20 Car bmw = SimpleCarFactory.createCar("寶馬"); 21 aodi.run(); 22 bmw.run(); 23 24 // 2、工廠方法 25 Car aodi1 = new AoDiFactory().createCar(); 26 Car jili1 = new BmwFactory().createCar(); 27 aodi1.run(); 28 jili1.run(); 29 } 30 } 31 32 // Car 產品 33 interface Car { 34 35 void run(); 36 } 37 38 class Bmw implements Car { 39 40 @Override 41 public void run() { 42 System.out.println("Bmw"); 43 } 44 } 45 46 class AoDi implements Car { 47 48 @Override 49 public void run() { 50 System.out.println("AoDi"); 51 } 52 } 53 54 // 1、簡單工廠 55 class SimpleCarFactory { 56 57 public static Car createCar(String name) { 58 if ("".equals(name)) { 59 return null; 60 } 61 if (name.equals("奧迪")) { 62 return new AoDi(); 63 } 64 if (name.equals("寶馬")) { 65 return new Bmw(); 66 } 67 return null; 68 } 69 } 70 71 72 // 2、工廠方法 73 interface MethodCarFactory { 74 75 Car createCar(); 76 } 77 78 class AoDiFactory implements MethodCarFactory { 79 80 public Car createCar() { 81 return new AoDi(); 82 } 83 } 84 85 class BmwFactory implements MethodCarFactory { 86 87 public Car createCar() { 88 return new Bmw(); 89 } 90 } 91 92 // 3、抽象工廠 93 // 發動機產品 94 interface Engine { 95 void run(); 96 } 97 class EngineA implements Engine { 98 public void run() { 99 System.out.println("轉的快!"); 100 } 101 } 102 class EngineB implements Engine { 103 public void run() { 104 System.out.println("轉的慢!"); 105 } 106 } 107 108 interface TotalFactory { 109 // 創建汽車 110 Car createChair(); 111 // 創建發動機 112 Engine createEngine(); 113 } 114 // 上海工廠實現類,由他決定調用哪個工廠的那個實例 115 class ShanghaiFactory implements TotalFactory { 116 public Engine createEngine() { 117 return new EngineA(); 118 } 119 public Car createChair() { 120 return new AoDi(); 121 } 122 }View Code
4.3 模版模式
使用場景:
資料庫訪問的封裝、Junit單元測試、servlet中關於doGet/doPost方法的調用
註意事項:
代碼實現:
1 package com.leo.basic.code.design; 2 3 /** 4 * @DESCRIPTION 5 * 模版:定義一個操作中的演算法骨架(父類),而將一些步驟延遲到子類中,是一個流程!!。主要子類不能覆蓋父類的模版方法!!! 6 * 優點:公共的邏輯代碼抽取,代碼復用;封裝不變的部分,重寫可變的部分,易擴展 7 * 缺點:每來一個子類就要定義一套子類的規範,項目的體積會越來越大 8 * @DATE 2022-11-02 9 * @AUTHOR liuzhilong 10 */ 11 public class TemplateTest { 12 13 public static void main(String[] args) { 14 RestaurantTemplate restaurantTemplate = new RestaurantLobsterImpl(); 15 restaurantTemplate.process(); 16 } 17 } 18 19 abstract class RestaurantTemplate { 20 21 // 1.看菜單 22 public void menu() { 23 System.out.println("看菜單"); 24 } 25 26 // 2.點菜業務 27 abstract void spotMenu(); 28 29 // 3.吃飯業務 30 public void havingDinner() { 31 System.out.println("吃飯"); 32 } 33 34 // 4.付款業務 35 abstract void payment(); 36 37 // 5.走人 38 public void goR() { 39 System.out.println("走人"); 40 } 41 42 //模板通用結構 43 public void process() { 44 menu(); 45 spotMenu(); 46 havingDinner(); 47 payment(); 48 goR(); 49 } 50 } 51 52 class RestaurantLobsterImpl extends RestaurantTemplate { 53 54 void spotMenu() { 55 System.out.println("龍蝦"); 56 } 57 58 void payment() { 59 System.out.println("50塊"); 60 } 61 }View Code
4.4 策略模式
使用場景:
策略模式的用意是針對一組演算法或邏輯,將每一個演算法或邏輯封裝到具有共同介面的獨立的類中,從而使得它們之間可以相互替換註意事項:
代碼實現:
1 package com.leo.basic.code.design; 2 3 /** 4 * @DESCRIPTION 5 * 策略:定義了一系列的演算法 或 邏輯 或 相同意義的操作,並將每一個演算法、邏輯、操作封裝起來,而且使它們還可以相互替換。 6 * 註意策略針對的是一個點,是一個演算法,不是流程。針對每個點實現一個具體的實現類,這點和模版方法不同!!! 7 * 優點:1、演算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性非常良好 8 * 缺點:1、策略類會增多。 2、所有策略類都需要對外暴露。 9 * @DATE 2022-11-02 10 * @AUTHOR liuzhilong 11 */ 12 public class StrategyTest { 13 14 public static void main(String[] args) { 15 Context context; 16 //使用支付邏輯A 17 context = new Context(new PayStrategyA()); 18 context.algorithmInterface(); 19 //使用支付邏輯B 20 context = new Context(new PayStrategyB()); 21 context.algorithmInterface(); 22 } 23 } 24 25 abstract class PayStrategy { 26 27 // 支付邏輯方法 28 abstract void algorithmInterface(); 29 } 30 31 class PayStrategyA extends PayStrategy { 32 33 void algorithmInterface() { 34 System.out.println("微信支付"); 35 } 36 } 37 38 class PayStrategyB extends PayStrategy { 39 40 void algorithmInterface() { 41 System.out.println("支付寶支付"); 42 } 43 } 44 45 //定義下文維護演算法策略 46 class Context { 47 48 PayStrategy strategy; 49 50 public Context(PayStrategy strategy) { 51 this.strategy = strategy; 52 } 53 54 public void algorithmInterface() { 55 strategy.algorithmInterface(); 56 } 57 }View Code
4.5 適配器模式
使用場景:
註意事項:
代碼實現:
1 package com.leo.basic.code.design; 2 3 /** 4 * @DESCRIPTION 5 * 適配器:將一個類的介面轉換成客戶希望的另外一個介面 6 * 優點:讓原本因介面不匹配不能在一起工作的兩個類可以協同工作 7 * 缺點: 8 * @DATE 2022-11-03 9 * @AUTHOR liuzhilong 10 */ 11 public class AdapterTest { 12 13 public static void main(String[] args) { 14 // 1、類適配器 15 //電腦,適配器,網線 16 Computer computer = new Computer();//電腦 17 Adapter adapter = new Adapter();//轉接器 18 computer.net(adapter);//電腦直接連接轉接器就可以 19 20 // 2、對象適配器 21 Adapter2 adapter2 = new Adapter2(new Adaptee());//轉接器 22 computer.net(adapter2); 23 24 } 25 } 26 27 // 1、類適配器 28 //要適配的類:網線 -- Adaptee 29 class Adaptee { 30 31 //功能:上網 32 public void request() { 33 System.out.println("鏈接網線上網"); 34 } 35 } 36 37 //介面轉換器的抽象實現 -- target 38 interface NetToUsb { 39 //作用:處理請求,網線=>usb 40 public void handleRequest(); 41 } 42 43 //真正的適配器,餘姚鏈接usb,連接網線 -- Adapter 44 class Adapter extends Adaptee implements NetToUsb{ 45 @Override 46 public void handleRequest() { 47 super.request();//可以上網了 48 } 49 } 50 51 //客戶端類:想上網,插不上網線 52 class Computer { 53 //電腦需要連接上轉接器才可以上網 54 public void net(NetToUsb adapter){ 55 //上網的具體實現:找一個轉接頭 56 adapter.handleRequest(); 57 } 58 } 59 60 // 2、對象適配器 61 class Adapter2 implements NetToUsb { 62 private Adaptee adaptee; 63 public Adapter2(Adaptee adaptee){ 64 this.adaptee = adaptee; 65 } 66 @Override 67 public void handleRequest() { 68 adaptee.request();;//可以上網了 69 } 70 }View Code
4.6 建造者模式
使用場景:
需要生成的對象具有複雜的內部結構;需要生成的對象內部屬性本身相互依賴
註意事項:
代碼實現:
1 package com.leo.basic.code.design; 2 3 /** 4 * @DESCRIPTION 5 * 建造者:是將一個複雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的方式進行創建 6 * 與工廠模式的區別是:建造者模式更加關註零件裝配的順序 7 * 優點: 8 * 缺點: 9 * @DATE 2022-11-02 10 * @AUTHOR liuzhilong 11 */ 12 public class BuilderTest { 13 14 public static void main(String[] args) { 15 PersonDirector pb = new PersonDirector();