创建型模型:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

创建型模型(根据不同业务创建对象)

单例(包含5种实现方式)

为了确保内存只提供一个实例对象。缺点是功能不方便扩展、有时单例功能过重有违单一原则。

饿汉模式(调用效率高,但是不能延时加载)

1
2
3
4
5
6
7
8
// 饿汉式非常“饿” 上来就直接new一个对象 不管后面会不会用到
private static HungerySingleton h = new HungerySingleton();

// 私有构造器
private HungerySingleton() {};

// 供外部拿到该对象
public static HungerySingleton getInstance() {return h;}

懒汉模式(调用效率不高,但是可以延时加载)

1
2
3
4
5
6
7
8
9
10
11
12
13
// 懒汉式一开始不会初始化,等到用的时候初始化
private static LazySingleton instance;

// 私有构造器
private LazySingleton() {};

// 需要添加synchronized,方法同步调用效低
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}

双重检测锁式(由于JVM底层内部模型原因,偶尔会出现问题,不建议使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
private static DoubleCheckSingleton instance = null;

// 私有化构造器
private DoubleCheckSingleton() {};

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

静态内部类式(调用效率高,可以延时加载)

1
2
3
4
5
6
7
8
9
10
11
// 私有化构造器
private StaticClassSingleton() {};

// 静态内部类
private static class StaticClassSingletonInstance {
private static final StaticClassSingleton instance = new StaticClassSingleton();
}

public static StaticClassSingleton getInstance() {
return StaticClassSingletonInstance.instance;
}

枚举单例(调用效率高,不能延时加载)

1
2
3
4
5
6
7
8
9
public enum EnumSingleton {
// 这个枚举元素本身就是单例的
INSTANCE;

// 添加自己的操作
public void singletonOperation() {

}
}

构造器(builder模式)

方便用户创建复杂的对象(不需要知道实现过程)。
代码复用性(将对象构建过程和细节进行封装),提高了维护性。

原型模式

工厂模式

简单工厂(静态工厂模式)

为了避免过多的依赖,通过调用不同生产方法得到同一接口下的不用实例,缺点是不改变工厂类代码不能新增产品。以下为举例:

  1. 普通接口实现
    1
    2
    3
    4
    5
    6
    7
    public static void main(String[] args) {
    Car c1 = new Audi();
    Car c2 = new Byd();

    c1.run();
    c2.run();
    }
  2. 简单工厂实现
    1
    2
    3
    4
    5
    6
    7
    public static void main(String[] args) {
    Car c1 = CarFactory.createCar("奥迪"); // createAudi()
    Car c2 = CarFactory.createCar("比亚迪"); // createByd()

    c1.run();
    c2.run();
    }

工厂方法模式

工厂方法模式会有一个总的工厂接口,然后为每一个类创建一个工厂,支持新增产品。(设计复杂度还是管理难度上面都要劣于简单工厂模式,建议使用简单工厂模式)

1
2
3
4
5
6
7
8
9
10
11
public interface CarFactory {
Car createCar();
}
public class AudiFactory implements CarFactory {
@Override
public Car createCar() {return new Audi();}
}
public class BydFactory implements CarFactory {
@Override
public Car createCar() {return new Byd();}
}  

抽象工厂

区别其他工厂模式,此模式是生成不同级别的产品;将产品功能进行接口抽象后,提供一个总的抽象工厂类,之后提供各级别工厂类来生产实例。

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
// 总的抽象工厂类
public interface CarFactory {
Engine createEngine(); // 创建引擎的接口
Seat createSeat();// 创建座位的接口
Tyre createTyre();// 创建轮胎的接口
}

// 生成高级车的工厂类
public class LuxuryCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LuxuryEngine();
}

@Override
public Seat createSeat() {
return new LuxurySeat();
}

@Override
public Tyre createTyre() {
return new LuxuryTyre();
}
}
// 生成低级车的工厂类
public class LowCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LowEngine();
}

@Override
public Seat createSeat() {
return new LowSeat();
}

@Override
public Tyre createTyre() {
return new LowTyre();
}
}

结构型模式(从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题)

适配器模式

将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作,使用场景比如做旧系统改造和升级。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 首先准备目标接口,这个接口是供客户端调用的
public interface Target {
void handleReq();
}
// 准备被适配的类
public class Adaptee {
public void request() {
System.out.println("可以完成客户请求的需要功能!");
}
}
// 适配器(一种是直接继承被适配的类,该方式的缺点是java只能单继承,无法完成适配多个类;第二种是使用对象组合的方式)
public class Adapter implements Target {
private Adaptee adaptee;

public Adapter(Adaptee adaptee) {
super();
this.adaptee = adaptee;
}

@Override
public void handleReq() {
adaptee.request();
}
}

桥接模式

装饰模式

动态的为一个对象增加新的功能,用于替代继承的技术,更加灵活,同时避免类型体系的快速膨胀。
形式和代理者模式很像,区别是代理模式用于控制对象访问,而装饰者用于新增对象功能。

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 抽象组件
public interface ICar {
void move();
}

// 真实对象,即被装饰对象
class Car implements ICar {
@Override
public void move() {
System.out.println("陆地上跑!");
}
}

// Decorate装饰器角色
class SuperCar implements ICar {
protected ICar iCar;

public SuperCar(ICar iCar) {
this.iCar = iCar;
}

@Override
public void move() {
iCar.move();
}
}

// ConcreateDecorate具体装饰角色
class FlyCar extends SuperCar {

public FlyCar(ICar iCar) {
super(iCar);
}

public void fly() {
System.out.println("天上飞");
}

@Override
public void move() {
fly();
super.move();
}
}

// ConcreateDecorate具体装饰角色
class WaterCar extends SuperCar {

public WaterCar(ICar iCar) {
super(iCar);
}

public void swim() {
System.out.println("水上游");
}

@Override
public void move() {
swim();
super.move();
}
}
// 使用
public static void main(String[] args) {
Car car = new Car();
car.move();

System.out.println("增加新功能,飞行");
FlyCar flyCar = new FlyCar(car);
flyCar.move();

System.out.println("继续增加水上跑");
WaterCar waterCar = new WaterCar(flyCar);
waterCar.move();
}

组合模式

外观模式

享元模式

代理模式

通过代理,控制对对象的访问。在调用某个方法前做前置处理,调用这个方法后做后置处理。

  1. 静态代理
  • 代理类和被代理类同时实现同一个接口,通过代理类传入被代理对象实现接口方法的调用
    1
    2
    3
    IUser ldh = new User();
    ProxyManger proxy = new ProxyManger(user);
    proxy.eat();
  1. 动态代理
  • 动态代理不需要实现接口(被代理对象还是要实现接口),利用jdk的api动态在在内存中创建代理对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    target;//为被代理对象
    return Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    target.getClass().getInterfaces(),
    new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //执行目标对象方法
    Object returnValue = method.invoke(target, args);
    return returnValue;
    }
    }
    );
  1. cglib代理
  • 通过继承父类实现代理

行为型模式

模板方法模式

命令模式

迭代器模式

观察者模式

中介者模式

备忘录模式

解释器模式

状态模式

策略模式

职责链模式

将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public abstract class Leader {
protected String name;
protected Leader nextLeader; // 责任链上的后继对象

public Leader(String name) {
this.name = name;
}
// 设置责任链的后继对象
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
}

// 处理请求的核心业务方法
public abstract void handleRequest(LeaveRequest lr);
}

public class Director extends Leader {
public Director(String name) {
super(name);
}

@Override
public void handleRequest(LeaveRequest lr) {
if (lr.getLeaveDays() < 3) {
System.out.println(String.format("员工%s请假%s,理由是%s", lr.getEmpName(), lr.getLeaveDays(), lr.getReason()));
System.out.println("主任" + this.name + "审批通过");
} else {
if (this.nextLeader != null) {
this.nextLeader.handleRequest(lr);
}
}
}
}

public class Manager extends Leader {
public Manager(String name) {
super(name);
}

@Override
public void handleRequest(LeaveRequest lr) {
if (lr.getLeaveDays() < 10) {
System.out.println(String.format("员工%s请假%s,理由是%s", lr.getEmpName(), lr.getLeaveDays(), lr.getReason()));
System.out.println("经理" + this.name + "审批通过");
} else {
if (this.nextLeader != null) {
this.nextLeader.handleRequest(lr);
}
}
}
}

public static void main(String[] args) {
Leader l1 = new Director("张三");
Leader l2 = new Manager("李四");
// 组织责任链的关系
l1.setNextLeader(l2);

// 开始请假操作
LeaveRequest lr = new LeaveRequest("TOM", 10, "回老家探亲");
l1.handleRequest(lr);
}

访问者模式

参考

23种设计模式——行为型模型
23种设计模式——结构型模型
23种设计模式——创建型模型