设计模式(创建型)

[TOC]

Ⅰ 懒汉式-线程不安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton{
private static Singleton s;
private Singleton(){

}
public static Singleton get uniqueInstance()
{
if(s==null)
{
s=new Singleton();
}
return s;
}
}

Ⅱ 饿汉式-线程安全

1
2
3
4
5
6
7
8
9
10
public class Singleton{
private static Singleton s =new Singleton();
private Singleton(){

}
public static Singleton get uniqueInstance()
{
return s;
}
}

Ⅲ 懒汉式-线程安全

但是当一个线程进入该方法之后,其它试图进入该方法的线程都必须等待,这会让线程阻塞时间过长,因此该方法有性能问题,不推荐使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton{
private static Singleton s;
public Singleton(){

}
public static synchronized Singleton get uniqueInstance()
{
if(s==null)
{
s=new Singleton();
}
return s;
}
}

Ⅳ 双重校验锁-线程安全

第一个 if 语句用来避免 uniqueInstance 已经被实例化之后的加锁操作,而第二个 if 语句进行了
加锁,所以只能有一个线程进入,就不会出现 uniqueInstance == null 时两个线程同时进行实例化操作。

uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实
是分为三步执行:

  1. 为 uniqueInstance 分配内存空间
  2. 初始化 uniqueInstance
  3. 将 uniqueInstance 指向分配的内存地址
    但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1>3>2。指令重排在单线程环境下不会出现问题,但是在
    多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用
    getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被
    初始化。
    使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Singleton{
public volatile static Singleton s;
public Singleton()
{

}
public static Singleton getInstance()
{
if(s==null)
{
synchronized(Singleton.class)
{
if(s==null)
{
s=new Singleton();
}
}

}
return s;
}
}

Ⅴ 静态内部类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton{
private Singleton()
{

}
private static class SingletonHolder{
private static final Singleton INSTANCE=new Singleton();
}
private static Singleton getInstance()
{
return SingletonHolder.INSTANCE;
}
}

简单工厂

简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来
实例化。

1
2
public interface Product {
}
1
2
public class ConcreteProduct implements Product {
}
1
2
public class ConcreteProduct1 implements Product {
}
1
2
public class ConcreteProduct2 implements Product {
}
1
2
3
4
5
6
7
8
9
10
public class SimpleFactory {
public Product createProduct(int type) {
if (type == 1) {
return new ConcreteProduct1();
} else if (type == 2) {
return new ConcreteProduct2();
}
return new ConcreteProduct();
}
}

具体实现

1
2
3
4
5
6
7
public class Client {
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
Product product = simpleFactory.createProduct(1);
// do something with the product
}
}

工厂方法

多个工厂,一种抽象产品。例如一个麦当劳店,可以生产多种汉堡,一个肯德基店,也可以生产多种汉堡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
作者:冠状病毒biss
链接:https://www.nowcoder.com/discuss/438905?type=all&order=time&pos=&page=1&channel=666&source_id=search_all
来源:牛客网

public interface HamburgerFactory {
Hamburger build();
}

class MCFactory implements HamburgerFactory {
@Override
public Hamburger build() {
return new MCHamburger();
}
}

class KFCFactory implements HamburgerFactory {
@Override
public Hamburger build() {
return new KFCHamburger();
}
}

interface Hamburger {
void eat();
}

class MCHamburger implements Hamburger {
@Override
public void eat() {
System.out.println("吃麦当劳汉堡");
}
}

class KFCHamburger implements Hamburger {
@Override
public void eat() {
System.out.println("吃肯德基汉堡");
}
}
public class test {
public static void main(String[] args) {
HamburgerFactory mcFactory=new MCFactory();
Hamburger hamburger=mcFactory.build();
hamburger.eat();
}
}

抽象工厂

img

抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建
出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。