diff --git a/notes/设计模式.md b/notes/设计模式.md index 85d11aad..afc4f65a 100644 --- a/notes/设计模式.md +++ b/notes/设计模式.md @@ -508,7 +508,13 @@ PizzaStore 由 orderPizza() 方法,顾客可以用它来下单。下单之后

-**5. 代码实现** +**5. 设计原则** + +**依赖倒置原则** :要依赖抽象,不要依赖具体类。听起来像是针对接口编程,不针对实现编程,但是这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或底层组件,两者都应该依赖于抽象。例如,下图中 Pizza 是抽象类,PizzaStore 和 Pizza 子类都依赖于 Pizza 这个抽象类。 + +

+ +**6. 代码实现** ```java public interface Pizza { @@ -606,27 +612,27 @@ ChicagoStyleCheesePizza is making.. ## 3. 抽象工厂模式 -**1. 设计原则** +**1. 模式定义** -**依赖倒置原则** :要依赖抽象,不要依赖具体类。听起来像是针对接口编程,不针对实现编程,但是这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或底层组件,两者都应该依赖于抽象。例如,下图中 PizzaStore 属于高层组件,它依赖的是 Pizza 的抽象类,这样就可以不用关心 Pizza 的具体实现细节。 +提供一个接口,用于创建 **相关对象家族** ,而不需要明确指定具体类。 -

+**2. 模式类图** -**2. 模式定义** +抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。 -提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。 +抽象工厂模式用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 CreateProductA 和 CreateProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。 -**3. 模式类图** +至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要这两个对象的协作才能完成任务。 -抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。并且,抽象工厂模式也用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 CreateProductA 和 CreateProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要这两个对象的协作才能完成任务。从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory ,而工厂模式使用了继承。 +从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory ,而工厂模式使用了继承。 -

+

-**4. 解决方案类图** +**3. 解决方案类图** -

+

-**5. 代码实现** +**4. 代码实现** ```java public interface Dough { @@ -795,7 +801,7 @@ private static Singleton uniqueInstance = new Singleton(); 因为 uniqueInstance 只需要被初始化一次,之后就可以直接使用了。加锁操作只需要对初始化那部分的代码进行,也就是说,只有当 uniqueInstance 没有被初始化时,才需要进行加锁。 -双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被初始化,那么才对初始化的语句进行加锁。如果只做一次判断,那么多个线程还是有可能同时进入实例化语句块的,因此需要仅此第二次的判断。 +双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被初始化,那么才对初始化的语句进行加锁。 ```java public class Singleton { @@ -818,6 +824,16 @@ public class Singleton { } ``` +考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是早晚的问题,也就是说会进行两次实例化,从而产生了两个实例。 + +```java +if (uniqueInstance == null) { + synchronized (Singleton.class) { + uniqueInstance = new Singleton(); + } +} +``` + # 命令模式 **1. 问题描述** diff --git a/pics/0de18cdb-e974-47a3-af47-9538edafe857.png b/pics/0de18cdb-e974-47a3-af47-9538edafe857.png new file mode 100644 index 00000000..ba797ed8 Binary files /dev/null and b/pics/0de18cdb-e974-47a3-af47-9538edafe857.png differ diff --git a/pics/967b2f5a-6ade-4ceb-bb41-493483fd3dff.png b/pics/967b2f5a-6ade-4ceb-bb41-493483fd3dff.png new file mode 100644 index 00000000..73a9046a Binary files /dev/null and b/pics/967b2f5a-6ade-4ceb-bb41-493483fd3dff.png differ