策略模式-观察者模式-装饰者模式-工厂模式-单例模式

时间:2021-03-09 21:56:52

算是最近学设计模式(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或者报错)。