策略模式-觀察者模式-裝飾者模式-工廠模式-單例模式


算是最近學設計模式(HEAD FIRST設計模式)的一個總結吧,力求用最精簡的代碼說明其設計本質。

第一個模式:策略模式

代碼:

 1 interface refuel {
 2     public void fuelUp();
 3 }
 4 
 5 
 6 class car {
 7     refuel fuelType;
 8 
 9     public void setFuelType(refuel type) {
10         this.fuelType = type;
11     }
12 
13     public void fuelUp() {
14         fuelType.fuelUp();
15     }
16 
17 }
18 
19 
20 class fuelUpWith_93 implements refuel {
21 
22     @Override
23     public void fuelUp() {
24         System.out.println("Fueled up with No.93 gasoline");
25     }
26 
27 }
28 
29 
30 class fuelUpWith_97 implements refuel {
31 
32     @Override
33     public void fuelUp() {
34         System.out.println("Fueled up with No.97 gasoline");
35     }
36 
37 }

說明:汽車都需要加油,但是不同汽車加不同的油,通過讓汽車持有一個具體實現加油算法的對象(通常向上轉型為其接口),在汽車加油的時候直接調用這個接口,讓其自己實現這種汽車加油的相關算法。

設計思想:解耦合,這個設計模式最大的優點是:能保證復用所有相同的代碼(只要你的汽車持有了其使用的汽油類型),又能保證當你需要一種新的實現的時候可以快速加入進去(寫一種實現基礎接口的算法實現)而不需要修改原有代碼。

第二個設計模式:觀察者模式

代碼(JAVA內置實現):

 1 import java.util.Observable;
 2 import java.util.Observer;
 3 
 4 public class Main {
 5 
 6     public static void main(String[] args) {
 7         School highSchool = new School();
 8         Student Jack = new Student("Jack");
 9         Student Tom = new Student("Tom");
10         Jack.register(highSchool);
11         Tom.register(highSchool);
12         highSchool.termBegins();
13     }
14 }
15 
16 
17 class School extends Observable {
18 
19     public void termBegins() {
20         this.setChanged();
21         this.notifyObservers();
22     }
23 
24 }
25 
26 
27 class Student implements Observer {
28 
29     Observable o;
30     String name;
31 
32     public Student(String name) {
33         this.name = new String(name);
34     }
35 
36     public void register(Observable o) {
37         this.o = o;
38         o.addObserver(this);
39     }
40 
41     @Override
42     public void update(Observable o, Object arg) {
43         if (o instanceof School) {
44             System.out.println(name + " go to schoole");
45         }
46     }
47 
48 }

代碼(手動實現):

 1 import java.util.ArrayList;
 2 
 3 public class Main {
 4 
 5     public static void main(String[] args) {
 6         Student Jack = new Student("Jack");
 7         Student Tom = new Student("Tom");
 8         School highSchool = new School();
 9         highSchool.register(Jack);
10         highSchool.register(Tom);
11         highSchool.termBegins();
12     }
13 }
14 
15 
16 class School {
17 
18     ArrayList<Student> stuList = new ArrayList<Student>();
19 
20     public void register(Student stu) {
21         stuList.add(stu);
22     }
23 
24     public void termBegins() {
25         this.notifyObservers();
26         System.out.println("Welcome to school!");
27     }
28 
29     private void notifyObservers() {
30         for (Student stu : stuList) {
31             stu.update();
32         }
33     }
34 }
35 
36 
37 class Student {
38 
39     String name;
40 
41     public Student(String name) {
42         this.name = new String(name);
43     }
44 
45     public void update() {
46         System.out.println(name + " go to school");
47     }
48 
49 }

說明:把學生(觀察者)對象交給學校(被觀察者)。當學校開學時,一個一個去“通知”,讓其持有的學生對象作出對應的反應。

設計思想:當需要變化的時候通知觀察者們。Swing組件中大量用到(反應鼠標點擊消息等等)。其他沒啥很特別的東西。

第三個設計模式:裝飾者模式
代碼:

 1 public class Main {
 2 
 3     public static void main(String[] args) {
 4         coffee myCoffee = new Mocha(new Milk(new regularCoffee()));
 5         System.out.println(myCoffee.getName());
 6     }
 7 }
 8 
 9 
10 interface coffee {
11 
12     public int getCost();
13 
14     public String getName();
15 
16 }
17 
18 
19 class regularCoffee implements coffee {
20 
21     @Override
22     public int getCost() {
23         return 5; // 最最普通的一杯咖啡底價5元
24     }
25 
26     @Override
27     public String getName() {
28         return "咖啡"; // 最最普通的咖啡
29     }
30 
31 }
32 
33 
34 abstract class coffeeDecorator implements coffee {
35 
36     coffee oriCoffee;
37 
38 }
39 
40 
41 class Milk extends coffeeDecorator { // 牛奶,加牛奶的修飾器
42 
43     public Milk(coffee c) {
44         this.oriCoffee = c;
45     }
46 
47     @Override
48     public int getCost() {
49         return oriCoffee.getCost() + 3; // 加一份牛奶再加3元
50     }
51 
52     @Override
53     public String getName() {
54         return "牛奶" + oriCoffee.getName(); // 加一份牛奶的話,名字上也要加一份牛奶前綴
55     }
56 
57 }
58 
59 
60 class Mocha extends coffeeDecorator { // 摩卡,加巧克力的修飾器
61 
62     public Mocha(coffee c) {
63         this.oriCoffee = c;
64     }
65 
66     @Override
67     public int getCost() {
68         return oriCoffee.getCost() + 4; // 加一份巧克力再叫4元
69     }
70 
71     @Override
72     public String getName() {
73         return "摩卡" + oriCoffee.getName(); // 加一份巧克力的話,名字也加一個前綴
74     }
75 
76 }

說明:每一次新建一個裝飾者(Mocha或者Milk或者你寫的別的什么),都依賴於一個傳入的參數(目前的咖啡),在這個基礎上繼續添加裝飾。

設計思想:一些類可能有自由組合的可能(比如咖啡),你很難一次把他們寫全(從設計上也不應該如此),於是便應該用裝飾者模式讓使用者自己去搭配。每一次經過修飾就在傳入參數的基礎上進行修改。

第四個設計模式:工廠模式

首先要說的是工廠模式這個名字讓人迷惑,因為很多模式好像都和工廠模式有關系:

1,靜態工廠模式 : 一般是說用靜態方法寫的簡單工廠模式。

2,簡單工廠模式 :就是一個類,里面封裝了某個類的構造方法,不僅調配構造參數,也許還有別的工作要做。

3,工廠方法模式 :在工廠中定義一個創建對象的接口,但是讓子類去實現(通過Abstract)具體的創建過程。(和模板方法模式有點像)

4,抽象工廠模式 :提供一個接口,用來創建相關或依賴對象的家族。

關於工廠方法模式和抽象工廠模式可以看:看這篇文章

 

第五個設計模式:單例模式
代碼(餓漢模式):

 1 class Singleton {
 2 
 3     private static Singleton instance = new Singleton();
 4 
 5     private Singleton() {
 6 
 7     }
 8 
 9     public static Singleton getInstance() {
10         return instance;
11     }
12 
13 }

 

說明:餓漢模式就是直接在類的靜態字段中寫上一個實例對象。由<clinit>方法自動在類加載結束的時候進行創建。JVM會保證類的加載線程安全,所以這種情況基本上不需要考慮多線程情況下的線程安全。但是問題還是有:生命周期不可以控制,這個類一加載就存在一個實例對象。

代碼(懶漢模式,雙重檢查模式+volatile):

 1 class Singleton {
 2 
 3     private volatile static Singleton instance;
 4 
 5     private Singleton() {
 6 
 7     }
 8 
 9     public static Singleton getInstance() {
10         if (instance == null) {
11             synchronized (Singleton.class) {
12                 if (instance == null) {
13                     return new Singleton();
14                 }
15             }
16         }
17         return instance;
18     }
19 }

說明:看這篇文章的說明

設計思想:很多類只需要有一個實例,也許只能有一個實例,當嘗試獲取多個實例時會返回相同一個實例對象(或者返回null或者報錯)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM