auto commit
This commit is contained in:
parent
3dd3a14385
commit
2b709d2f6a
|
@ -61,7 +61,7 @@
|
|||
|
||||
**多用组合,少用继承** 组合也就是 has-a 关系,通过组合,可以在运行时动态改变实现,只要通过改变父类对象具体指向哪个子类即可。而继承就不能做到这些,继承体系在创建类时就已经确定。
|
||||
|
||||
运用这一原则,在 Duck 类中组合 FlyBehavior 和 QuackBehavior 类,performQuack() 和 performFly() 方法委托给这两个类去处理。通过这种方式,一个 Duck 子类可以根据需要去实例化 FlyBehavior 和 QuackBehavior 的子类对象,并且也可以动态地进行改变。
|
||||
运用这一原则,在 Duck 类中组合 FlyBehavior 和 QuackBehavior 类,performQuack() 和 performFly() 方法委托给这两个类去处理。通过这种方式,一个 Duck 子类可以根据需要去初始化 FlyBehavior 和 QuackBehavior 的子类对象,并且也可以动态地进行改变。
|
||||
|
||||
<div align="center"> <img src="../pics//29574e6f-295c-444e-83c7-b162e8a73a83.jpg"/> </div><br>
|
||||
|
||||
|
@ -752,15 +752,17 @@ MarinaraSauce
|
|||
|
||||
**2. 模式类图**
|
||||
|
||||
使用一个私有构造器、一个私有静态变量以及一个公有静态函数来实现。私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
|
||||
使用一个私有构造器、一个私有静态变量以及一个公有静态函数来实现。
|
||||
|
||||
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
|
||||
|
||||
<div align="center"> <img src="../pics//59aff6c1-8bc5-48e4-9e9c-082baeb2f274.jpg"/> </div><br>
|
||||
|
||||
**3. 懒汉式-线程不安全**
|
||||
|
||||
以下实现中,私有静态变量被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会创建私有静态变量,从而节约资源。
|
||||
以下实现中,私有静态变量被延迟化实例化,这样做的好处是,如果没有用到该类,那么就不会实例化私有静态变量,从而节约资源。
|
||||
|
||||
这个实现在多线程环境下是不安全的,如果多个线程能够同时进入 if(uniqueInstance == null) 内的语句块,那么就会多次实例化 uniqueInstance 私有静态变量。
|
||||
这个实现在多线程环境下是不安全的,如果多个线程能够同时进入`if(uniqueInstance == null)` ,那么就会多次实例化 uniqueInstance。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
|
@ -781,20 +783,22 @@ public class Singleton {
|
|||
|
||||
**4. 懒汉式-线程安全**
|
||||
|
||||
只需要对 getUniqueInstance() 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。但是这样有一个问题,就是当一个线程进入该方法之后,其它线程视图进入该方法都必须等待,因此性能上有一定的损耗。
|
||||
只需要对 `getUniqueInstance()` 方法加锁,那么在一个时间点只能有一个线程能够进入该方法,从而避免了对 uniqueInstance 进行多次实例化的问题。
|
||||
|
||||
但是这样有一个问题,就是当一个线程进入该方法之后,其它线程试图进入该方法都必须等待,因此性能上有一定的损耗。
|
||||
|
||||
```java
|
||||
public static synchronized Singleton getUniqueInstance() {
|
||||
if (uniqueInstance == null) {
|
||||
uniqueInstance = new Singleton();
|
||||
}
|
||||
return uniqueInstance;
|
||||
public static synchronized Singleton getUniqueInstance() {
|
||||
if (uniqueInstance == null) {
|
||||
uniqueInstance = new Singleton();
|
||||
}
|
||||
return uniqueInstance;
|
||||
}
|
||||
```
|
||||
|
||||
**5. 饿汉式-线程安全**
|
||||
|
||||
线程不安全问题主要是由于静态实例变量被初始化了多次,那么静态实例变量采用直接实例化就可以解决问题。但是直接初始化的方法也丢失了延迟初始化节约资源的优势。
|
||||
线程不安全问题主要是由于 uniqueInstance 被实例化了多次,如果 uniqueInstance 采用直接实例化的话,就不会被实例化多次,也就不会产生线程不安全问题。但是直接实例化的方式也丢失了延迟实例化带来的节约资源的优势。
|
||||
|
||||
```java
|
||||
private static Singleton uniqueInstance = new Singleton();
|
||||
|
@ -802,9 +806,9 @@ private static Singleton uniqueInstance = new Singleton();
|
|||
|
||||
**6. 双重校验锁-线程安全**
|
||||
|
||||
因为 uniqueInstance 只需要被初始化一次,之后就可以直接使用了。加锁操作只需要对初始化那部分的代码进行,也就是说,只有当 uniqueInstance 没有被初始化时,才需要进行加锁。
|
||||
uniqueInstance 只需要被实例化一次,之后就可以直接使用了。加锁操作只需要对实例化那部分的代码进行。也就是说,只有当 uniqueInstance 没有被实例化时,才需要进行加锁。
|
||||
|
||||
双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被初始化,那么才对初始化的语句进行加锁。
|
||||
双重校验锁先判断 uniqueInstance 是否已经被初始化了,如果没有被实例化,那么才对实例化语句进行加锁。
|
||||
|
||||
```java
|
||||
public class Singleton {
|
||||
|
@ -827,7 +831,7 @@ public class Singleton {
|
|||
}
|
||||
```
|
||||
|
||||
考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton(); 这条语句,只是早晚的问题,也就是说会进行两次实例化,从而产生了两个实例。
|
||||
考虑下面的实现,也就是只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程同时执行 if 语句,那么两个线程就会同时进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 `uniqueInstance = new Singleton();`这条语句,只是早晚的问题,也就是说会进行两次实例化,从而产生了两个实例。因此必须使用双重校验锁,也就是需要使用两个 if 判断。
|
||||
|
||||
```java
|
||||
if (uniqueInstance == null) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user