设计模式笔记——GoF设计模式汇总

目录

· 总述php

    · 记忆css

    · 效果java

    · 面向对象设计原则ios

· 建立型模式正则表达式

    · 单例模式(Singleton)算法

        · 效果数据库

        · 分类编程

        · 代码(饿汉式)设计模式

        · 代码(懒汉式)安全

        · 代码(双重检测锁式)

        · 代码(静态内部类式)

        · 代码(枚举单例)

        · 代码(使用反射的破解与防护)

        · 代码(使用序列化的破解与防护)

        · 应用场景

    · 工厂模式

        · 效果

        · 分类

        · 代码(简单工厂)

        · 代码(工厂方法)

        · 代码(抽象工厂)

        · 应用场景

    · 构建者模式(Builder)

        · 效果

        · 代码

        · 应用场景

    · 原型模式(Prototype)

        · 效果

        · 核心角色

        · 代码(浅克隆)

        · 代码(基于JDK的深克隆)

        · 代码(基于序列化的深克隆)

        · 应用场景

· 结构型模式

    · 适配器模式(Adapter)

        · 效果

        · 核心角色

        · 分类

        · 代码(使用继承)

        · 代码(使用关联)

        · 应用场景

    · 代理模式(Proxy)

        · 效果

        · 核心角色

        · 分类

        · 代码(静态代理)

        · 代码(动态代理)

        · 应用场景

    · 桥接模式(Bridge)

        · 效果

        · 代码

        · 应用场景

    · 组合模式(Composite)

        · 效果

        · 核心角色

        · 代码

        · 代码(杀毒举例)

        · 应用场景

    · 装饰器模式(Decorator)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

    · 外观模式(Facade)

        · 效果

        · 代码

        · 应用场景

    · 享元模式(FlyWeight)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

· 行为型模式

    · 责任链模式(Chain of Resposibility)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

    · 迭代器模式(Iterator)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

    · 中介者模式(Mediator)

        · 效果

        · 代码

        · 应用场景

    · 命令模式(Command)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

    · 解释器模式(Interpreter)

        · 效果

        · 应用场景

    · 访问者模式(Visitor)

        · 效果

        · 应用场景

    · 策略模式(Strategy)

        · 效果

        · 代码

        · 应用场景

    · 模板方法模式(Template Method)

        · 效果

        · 代码

        · 应用场景

    · 状态模式(State)

        · 效果

        · 核心角色

        · 代码

        · 应用场景

    · 观察者模式(Observer)

        · 效果

        · 代码

        · 代码(基于JDK)

        · 应用场景

    · 备忘录模式(Memento)

        · 效果

        · 核心角色

        · 代码

        · 应用场景


 

总述

记忆

1. 建立型:sbfp;

2. 结构型:abcdffp;

3. 行为型:iimmccsstov。

效果

1. 全部面向对象设计原则和设计模式都是为了下降代码耦合度,提升扩展性、复用,手段是“分工”。

2. 相似社会分工,现代社会比原始社会发展得大,也是由于分工。

面向对象设计原则 

首字母

代指

解释

S

单一功能原则(Single Responsibility Principle)

对象应该仅具备一种单一功能。

O

开闭原则(Open/Closed Principle)

软件体应该是对于扩展开放的,可是对于修改封闭的。

L

里氏替换原则(Liskov Substitution Principle)

程序中的对象应该是能够在不改变程序正确性的前提下被它的子类所替换的。

I

接口隔离原则(Interface Segregation Principle)

多个特定客户端接口要好于一个宽泛用途的接口。

D

依赖反转原则(Dependency Inversion Principle)

一个方法应该听从依赖于抽象而不是一个实例

建立型模式

单例模式(Singleton)

效果

1. 保证一个类只有一个实例,而且提供一个访问该实例的全局访问点。

2. 因为单例模式只生成一个实例,减小了系统性能开销,当一个对象的产生须要比较多的资源时,如读取配置、产生其余依赖对象时,则能够经过在应用启动时直接产生一个单例对象,而后永久驻留内存的方式来解决。

分类

1. 常见实现方式。

    a) 饿汉式:线程安全,调用效率高,不能延时加载。

    b) 懒汉式:线程安全,调用效率不高,可延时加载。

2. 其余实现方式。

    a) 双重检测锁式:因为JVM底层内部模型缘由,偶尔出问题,不建议使用。

    b) 静态内部类式:线程安全,调用效率高,可延时加载。

    c) 枚举单例:线程安全,调用效率高,不能延时加载。

3. 选择方法。

    a) 单例对象占用资源少,不须要延时加载:枚举式好于饿汉式;

    b) 单例对象占用资源多,须要延时加载:静态内部类好于懒汉式。

代码(饿汉式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     // 类初始化时当即建立对象
 4     private static final Singleton instance = new Singleton();
 5     
 6     // 私有化构造器
 7     private Singleton() {
 8         if (instance != null) {
 9             throw new RuntimeException();
10         }
11     }
12     
13     public static Singleton getInstance() {
14         return instance;
15     }
16     
17 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代码(懒汉式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     private static Singleton instance;
 4     
 5     // 私有化构造器
 6     private Singleton() {
 7     }
 8     
 9     // 同步方法
10     public static synchronized Singleton getInstance() {
11         if (instance == null) {
12             // 延时加载
13             instance = new Singleton();
14         }
15         return instance;
16     }
17     
18 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代码(双重检测锁式)

1. Singleton.java

 1 public class Singleton {
 2 
 3     private static volatile Singleton instance;
 4     
 5     // 私有化构造器
 6     private Singleton() {
 7     }
 8     
 9     public static Singleton getInstance() {
10         if (instance == null) {
11             // 第一次建立时同步
12             synchronized (Singleton.class) {
13                 if (instance == null) {
14                     // 延时加载
15                     instance = new Singleton();
16                 }
17             }
18         }
19         return instance;
20     }
21     
22 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代码(静态内部类式)

1. Singleton.java

 1 public class Singleton {
 2     
 3     // 初始化外部类时不会当即初始化内部类
 4     private static class SingletonInstance {
 5         private static final Singleton instance = new Singleton();
 6     }
 7 
 8     // 私有化构造器
 9     private Singleton() {
10     }
11     
12     public static Singleton getInstance() {
13         return SingletonInstance.instance;
14     }
15     
16 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.getInstance();
5         Singleton singleton2 = Singleton.getInstance();
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代码(枚举单例)

1. Singleton.java

 1 public enum Singleton {
 2     
 3     // 枚举自己就是单例
 4     INSTANCE;
 5     
 6     // 添加须要的方法
 7     public void method() {
 8     }
 9     
10 }
View Code

2. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Singleton singleton1 = Singleton.INSTANCE;
5         Singleton singleton2 = Singleton.INSTANCE;
6         System.out.println(singleton1 == singleton2);
7     }
8 
9 }
View Code

代码(使用反射的破解与防护)

1. Singleton.java

 1 public class Singleton {
 2 
 3     // 类初始化时当即建立对象
 4     private static final Singleton instance = new Singleton();
 5     
 6     // 私有化构造器
 7     private Singleton() {
 8         // 防护:再次建立时抛出异常
 9         if (instance != null) {
10             throw new RuntimeException();
11         }
12     }
13     
14     public static Singleton getInstance() {
15         return instance;
16     }
17     
18 }
View Code

2. Client.java

 1 import java.lang.reflect.Constructor;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) throws Exception {
 6         Singleton singleton1 = Singleton.getInstance();
 7         
 8         Class<Singleton> clazz = Singleton.class;
 9         Constructor<Singleton> constructor = clazz.getDeclaredConstructor();
10         constructor.setAccessible(true);
11         Singleton singleton2 = constructor.newInstance();
12         System.out.println(singleton1 == singleton2);
13     }
14 
15 }
View Code

代码(使用序列化的破解与防护)

1. Singleton.java

 1 import java.io.Serializable;
 2 
 3 public class Singleton implements Serializable {
 4 
 5     private static final long serialVersionUID = -3230831923851678463L;
 6     
 7     // 类初始化时当即建立对象
 8     private static final Singleton instance = new Singleton();
 9     
10     // 私有化构造器
11     private Singleton() {
12     }
13     
14     public static Singleton getInstance() {
15         return instance;
16     }
17     
18     // 防护:反序列化时,直接返回该方法的返回值
19     private Object readResolve() {
20         return instance;
21     }
22     
23 }
View Code

2. Client.java

 1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.FileOutputStream;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 
 7 public class Client {
 8 
 9     public static void main(String[] args) throws Exception {
10         Singleton singleton1 = Singleton.getInstance();
11         
12         File tempFile = new File("D:/test");
13         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tempFile));
14         oos.writeObject(singleton1);
15         oos.close();
16         ObjectInputStream ios = new ObjectInputStream(new FileInputStream(tempFile));
17         Singleton singleton2 = (Singleton) ios.readObject();
18         ios.close();
19         System.out.println(singleton1 == singleton2);
20         
21     }
22 
23 }
View Code

应用场景

1. Windows的Task Manager(任务管理器)。

2. Windows的Recycle Bin(回收站)。

3. 项目中,读取配置文件的类,通常只有一个对象,不必每次建立。

4. 数据库链接池。

5. Application是单例的典型应用(Servlet编程)。

6. Spring中,每一个Bean默认是单例的。

7. 每一个Servlet是单例。

8. Spring MVC中,控制器对象是单例的。

工厂模式

效果

1. 实例化对象,用工厂方法代替new。实现了建立者和调用者的分离。

2. 将选择实现类、建立对象统一管理和控制,从而将调用者跟咱们的实现类解耦。

分类

1. 简单工厂模式:用来产生同一等级结构中的任意产品。对于增长新的产品,须要修改已有代码。

2. 工厂方法模式:用来产生同一等级结构中的固定产品。支持增长任意产品。

3. 抽象工厂模式:用来生产不一样产品族的所有产品。对于增长新的产品,无能为力;支持增长产品族。

4. 简单工厂模式效果:

    a) 又称静态工厂模式。

    b) 工厂类通常使用静态方法,经过接收的参数来返回不一样的对象实例。

    c) 对于增长新产品只能修改代码(违反OCP)。

    d) 有两种实现方式(见代码)。

5. 工厂方法模式效果:

    a) 避免简单工厂的缺点,但不彻底知足OCP。

    b) 简单工厂模式VS.工厂方法模式:

        i. 结构复杂度:显然简单工厂模式占优,简单工厂模式只要一个工厂,而工厂方法模式的工厂类随着产品类个数增长而增长。

        ii. 代码复杂度:代码复杂度与结构复杂度相反,简单工厂模式的工厂类随着产品增长须要增长更多方法(代码),而工厂方法模式每一个具体工厂类只完成单一任务,代码简单。

        iii. 客户端编程难度:工厂方法模式虽然知足了OCP,但客户端编码中须要对工厂实例化,而简单工厂模式的工厂类是一个静态类。

        iv. 管理上的难度:工厂方法模式须要维护的工厂类过多,而简单工厂模式只有一个。

    c) 设计理论建议使用工厂方法模式,但实际中通常都用简单工厂模式。

6. 抽象工厂模式效果:

    a) 用来生产不一样产品族的所有产品。对于增长新的产品,无能为力;支持增长产品族。

    b) 抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,经过抽象工厂模式产生须要的对象时一种很是好的解决方式。

代码(简单工厂)

1. Car.java

1 public interface Car {
2 
3     void run();
4     
5 }
View Code

2. Audi.java

1 public class Audi implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("奥迪在跑!");
6     }
7 
8 }
View Code

3. Byd.java

1 public class Byd implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("比亚迪在跑!");
6     }
7 
8 }
View Code

4. CarFactory.java

 1 // 一个方法实现
 2 public class CarFactory1 {
 3 
 4     public static Car createCar(String type) {
 5         if ("Audi".equals(type)) {
 6             return new Audi();
 7         }
 8         if ("Byd".equals(type)) {
 9             return new Byd();
10         }
11         return null;
12     }
13     
14 }
View Code

5. CarFactory2.java

 1 // 多个方法实现
 2 public class CarFactory2 {
 3     
 4     public static Car createAudi() {
 5         return new Audi();
 6     }
 7 
 8     public static Car createByd() {
 9         return new Byd();
10     }
11     
12 }
View Code

6. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Car car1 = CarFactory1.createCar("Audi");
 5         Car car2 = CarFactory1.createCar("Byd");
 6         car1.run();
 7         car2.run();
 8     }
 9 
10 }
View Code

代码(工厂方法)

1. Car.java

1 public interface Car {
2 
3     void run();
4     
5 }
View Code

2. CarFactory.java

1 public interface CarFactory {
2 
3     Car createCar();
4     
5 }
View Code

3. Audi.java

1 public class Audi implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("奥迪在跑!");
6     }
7 
8 }
View Code

4. AudiFactory.java

1 public class AudiFactory implements CarFactory {
2 
3     @Override
4     public Car createCar() {
5         return new Audi();
6     }
7 
8 }
View Code

5. Byd.java

1 public class Byd implements Car {
2 
3     @Override
4     public void run() {
5         System.out.println("比亚迪在跑!");
6     }
7 
8 }
View Code

6. BydFactory.java

1 public class BydFactory implements CarFactory {
2 
3     @Override
4     public Car createCar() {
5         return new Byd();
6     }
7 
8 }
View Code

7. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Car car1 = new AudiFactory().createCar();
 5         Car car2 = new BydFactory().createCar();
 6         car1.run();
 7         car2.run();
 8     }
 9 
10 }
View Code

代码(抽象工厂)

1. Engine.java

 1 public interface Engine {
 2 
 3     void start();
 4     
 5     void speedUp();
 6     
 7 }
 8 
 9 class LuxuryEngine implements Engine {
10     
11     @Override
12     public void start() {
13         System.out.println("快速启动!");
14     }
15     
16     @Override
17     public void speedUp() {
18         System.out.println("快速加速!");
19     }
20     
21 }
22 
23 class LowEngine implements Engine {
24 
25     @Override
26     public void start() {
27         System.out.println("慢速启动!");
28     }
29 
30     @Override
31     public void speedUp() {
32         System.out.println("慢速加速!");
33     }
34     
35 }
View Code

2. Seat.java

 1 public interface Seat {
 2 
 3     void massage();
 4     
 5 }
 6 
 7 class LuxurySeat implements Seat {
 8     
 9     @Override
10     public void massage() {
11         System.out.println("按摩!");
12     }
13     
14 }
15 
16 class LowSeat implements Seat {
17 
18     @Override
19     public void massage() {
20         System.out.println("不能按摩!");
21     }
22     
23 }
View Code

3. Tire.java

 1 public interface Tire {
 2 
 3     void revolve();
 4     
 5 }
 6 
 7 class LuxuryTire implements Tire {
 8 
 9     @Override
10     public void revolve() {
11         System.out.println("旋转不磨损!");
12     }
13     
14 }
15 
16 class LowTire implements Tire {
17 
18     @Override
19     public void revolve() {
20         System.out.println("旋转磨损快!");
21     }
22     
23 }
View Code

4. CarFactory.java

 1 public interface CarFactory {
 2 
 3     Engine createEngine();
 4     
 5     Seat createSeat();
 6     
 7     Tire createTire();
 8     
 9 }
10 
11 class LuxuryCarFactory implements CarFactory {
12     
13     @Override
14     public Engine createEngine() {
15         return new LuxuryEngine();
16     }
17     
18     @Override
19     public Seat createSeat() {
20         return new LuxurySeat();
21     }
22     
23     @Override
24     public Tire createTire() {
25         return new LuxuryTire();
26     }
27     
28 }
29 
30 class LowCarFactory implements CarFactory {
31 
32     @Override
33     public Engine createEngine() {
34         return new LowEngine();
35     }
36 
37     @Override
38     public Seat createSeat() {
39         return new LowSeat();
40     }
41 
42     @Override
43     public Tire createTire() {
44         return new LowTire();
45     }
46     
47 }
View Code

5. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         CarFactory carFactory = new LuxuryCarFactory();
 5         Engine engine = carFactory.createEngine();
 6         engine.start();
 7         engine.speedUp();
 8     }
 9 
10 }
View Code

应用场景

1. JDK中Calendar.getInstance()方法。

2. JDBC中Connection对象的获取。

3. Hibernate中SessionFactory建立Session。

4. Spring中IoC容器建立管理Bean对象。

5. 反射中Class对象的newInstance()方法。

构建者模式(Builder)

效果

1. 构建一个复杂的产品(如神舟飞船、iPhone)时,须要解决“如何装配子组件”的问题。

2. 分离了对象子组件的单独构建(Builder)和装配(Director),从而构造出复杂对象。

3. 因为实现了构建和装配的解耦。不一样的构建器、相同的装配,或者相同的构建器、不一样的装配,均可以建立不一样的对象。

4. 建造者模式通常与工厂模式搭配,由工厂模式建立子组件,再有建造者模式装配。

代码

1. Airship.java

 1 public class Airship {
 2 
 3     private Engine engine;
 4     
 5     private OrbitalModule orbitalModule;
 6     
 7     private EscapeTower escapeTower;
 8     
 9     public void launch() {
10         System.out.println(engine.getName() + "点火!");
11         System.out.println(orbitalModule.getName() + "发射!");
12     }
13 
14     public Engine getEngine() {
15         return engine;
16     }
17 
18     public void setEngine(Engine engine) {
19         this.engine = engine;
20     }
21 
22     public OrbitalModule getOrbitalModule() {
23         return orbitalModule;
24     }
25 
26     public void setOrbitalModule(OrbitalModule orbitalModule) {
27         this.orbitalModule = orbitalModule;
28     }
29 
30     public EscapeTower getEscapeTower() {
31         return escapeTower;
32     }
33 
34     public void setEscapeTower(EscapeTower escapeTower) {
35         this.escapeTower = escapeTower;
36     }
37     
38 }
39 
40 class Engine {
41     
42     private String name;
43     
44     public String getName() {
45         return name;
46     }
47     
48     public void setName(String name) {
49         this.name = name;
50     }
51     
52 }
53 
54 class OrbitalModule {
55     
56     private String name;
57     
58     public String getName() {
59         return name;
60     }
61     
62     public void setName(String name) {
63         this.name = name;
64     }
65     
66 }
67 
68 class EscapeTower {
69     
70     private String name;
71 
72     public String getName() {
73         return name;
74     }
75 
76     public void setName(String name) {
77         this.name = name;
78     }
79     
80 }
View Code

2. AirshipBuilder.java

1 public interface AirshipBuilder {
2 
3     Engine buildEngine();
4     
5     OrbitalModule buildOrbitalModule();
6     
7     EscapeTower buildEscapeTower();
8     
9 }
View Code

3. AirshipDirector.java

1 public interface AirshipDirector {
2 
3     Airship directAirship();
4     
5 }
View Code

4. SzAirshipBuilder.java

 1 public class SzAirshipBuilder implements AirshipBuilder {
 2 
 3     @Override
 4     public Engine buildEngine() {
 5         // 也可以使用工厂模式建立
 6         Engine engine = new Engine();
 7         engine.setName("神舟发动机");
 8         return engine;
 9     }
10 
11     @Override
12     public OrbitalModule buildOrbitalModule() {
13         // 也可以使用工厂模式建立
14         OrbitalModule orbitalModule = new OrbitalModule();
15         orbitalModule.setName("神舟轨道舱");
16         return orbitalModule;
17     }
18 
19     @Override
20     public EscapeTower buildEscapeTower() {
21         // 也可以使用工厂模式建立
22         EscapeTower escapeTower = new EscapeTower();
23         escapeTower.setName("神舟逃逸塔");
24         return escapeTower;
25     }
26 
27 }
View Code

5. SzAirshipDirector.java

 1 public class SzAirshipDirector implements AirshipDirector {
 2 
 3     private AirshipBuilder airshipBuilder;
 4     
 5     public SzAirshipDirector(AirshipBuilder airshipBuilder) {
 6         this.airshipBuilder = airshipBuilder;
 7     }
 8 
 9     @Override
10     public Airship directAirship() {
11         Engine engine = airshipBuilder.buildEngine();
12         OrbitalModule orbitalModule = airshipBuilder.buildOrbitalModule();
13         EscapeTower escapeTower = airshipBuilder.buildEscapeTower();
14         
15         Airship airship = new Airship();
16         airship.setEngine(engine);
17         airship.setOrbitalModule(orbitalModule);
18         airship.setEscapeTower(escapeTower);
19         
20         return airship;
21     }
22 
23 }
View Code

6. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         AirshipDirector airshipDirector = new SzAirshipDirector(new SzAirshipBuilder());
5         Airship airship = airshipDirector.directAirship();
6         airship.launch();
7     }
8     
9 }
View Code

应用场景

1. StringBuilder.append()方法。

2. SQL中的PareparedStatement。

原型模式(Prototype)

效果

1. 经过new建立对象须要很是繁琐的数据准备或访问权限,则可使用原型模式。

2. 就是Java中的克隆技术,以某个对象为原型,复制出新的对象。

3. 优点:效率高,避免从新执行构建过程。

4. 克隆相似于new,但不一样于new。new建立新的对象属性采用默认值。克隆出的对象属性彻底与原型对象相同,而且克隆出的新对象改变不会影响原型对象,而后再修改克隆对象的值。

核心角色

1. Clonable接口的clone()方法。

2. 实现原型模式最困难的是内存复制操做,所幸Java提供了clone()方法。

代码(浅克隆)

1. Sheep.java

 1 import java.util.Date;
 2 
 3 public class Sheep implements Cloneable {
 4 
 5     private String name;
 6     
 7     private Date birthday;
 8     
 9     @Override
10     protected Object clone() throws CloneNotSupportedException {
11         return super.clone();
12     }
13 
14     public String getName() {
15         return name;
16     }
17 
18     public void setName(String name) {
19         this.name = name;
20     }
21 
22     public Date getBirthday() {
23         return birthday;
24     }
25 
26     public void setBirthday(Date birthday) {
27         this.birthday = birthday;
28     }
29     
30 }
View Code

2. Client.java

 1 import java.util.Date;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) throws Exception {
 6         Sheep sheep1 = new Sheep();
 7         sheep1.setName("少利");
 8         sheep1.setBirthday(new Date());
 9         
10         Sheep sheep2 = (Sheep) sheep1.clone();
11         sheep2.setName("多利");
12         System.out.println(sheep2.getName());
13         System.out.println(sheep2.getBirthday());
14         
15         // 浅克隆
16         System.out.println(sheep1.getBirthday() == sheep2.getBirthday());
17     }
18 
19 }
View Code

代码(基于JDK的深克隆)

1. Sheep.java

 1 import java.util.Date;
 2 
 3 public class Sheep implements Cloneable {
 4 
 5     private String name;
 6     
 7     private Date birthday;
 8     
 9     @Override
10     protected Object clone() throws CloneNotSupportedException {
11         Sheep sheep = (Sheep) super.clone();
12         sheep.setBirthday((Date) birthday.clone());
13         return sheep;
14     }
15 
16     public String getName() {
17         return name;
18     }
19 
20     public void setName(String name) {
21         this.name = name;
22     }
23 
24     public Date getBirthday() {
25         return birthday;
26     }
27 
28     public void setBirthday(Date birthday) {
29         this.birthday = birthday;
30     }
31     
32 }
View Code

2. Client.java

 1 import java.util.Date;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) throws Exception {
 6         Sheep sheep1 = new Sheep();
 7         sheep1.setName("少利");
 8         sheep1.setBirthday(new Date());
 9         
10         Sheep sheep2 = (Sheep) sheep1.clone();
11         sheep2.setName("多利");
12         System.out.println(sheep2.getName());
13         System.out.println(sheep2.getBirthday());
14         
15         // 深克隆
16         System.out.println(sheep1.getBirthday() == sheep2.getBirthday());
17     }
18 
19 }
View Code

代码(基于序列化的深克隆)

1. Sheep.java

 1 import java.io.ByteArrayInputStream;
 2 import java.io.ByteArrayOutputStream;
 3 import java.io.IOException;
 4 import java.io.ObjectInputStream;
 5 import java.io.ObjectOutputStream;
 6 import java.io.Serializable;
 7 import java.util.Date;
 8 
 9 public class Sheep implements Cloneable, Serializable {
10 
11     private static final long serialVersionUID = 2155997264135266066L;
12 
13     private String name;
14     
15     private Date birthday;
16     
17     @Override
18     protected Object clone() throws CloneNotSupportedException {
19         Sheep sheep = null;
20         ByteArrayOutputStream baos = null;
21         ObjectOutputStream oos = null;
22         ByteArrayInputStream bais = null;
23         ObjectInputStream ois = null;
24         try {
25             baos = new ByteArrayOutputStream();
26             oos = new ObjectOutputStream(baos);
27             oos.writeObject(this);
28             byte[] bytes = baos.toByteArray();
29             bais = new ByteArrayInputStream(bytes);
30             ois = new ObjectInputStream(bais);
31             sheep = (Sheep) ois.readObject();
32             
33         } catch (IOException | ClassNotFoundException e) {
34             e.printStackTrace();
35         }
36         return sheep;
37     }
38 
39     public String getName() {
40         return name;
41     }
42 
43     public void setName(String name) {
44         this.name = name;
45     }
46 
47     public Date getBirthday() {
48         return birthday;
49     }
50 
51     public void setBirthday(Date birthday) {
52         this.birthday = birthday;
53     }
54     
55 }
View Code

2. Client.java

 1 import java.util.Date;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) throws Exception {
 6         Sheep sheep1 = new Sheep();
 7         sheep1.setName("少利");
 8         sheep1.setBirthday(new Date());
 9         
10         Sheep sheep2 = (Sheep) sheep1.clone();
11         sheep2.setName("多利");
12         System.out.println(sheep2.getName());
13         System.out.println(sheep2.getBirthday());
14         
15         // 深克隆
16         System.out.println(sheep1.getBirthday() == sheep2.getBirthday());
17     }
18 
19 }
View Code

应用场景

1. 原型模式不多单独使用,通常与工厂模式一块儿出现。经过clone()方法建立对象后由工厂模式返回。

2. Spring的Bean建立有单例模式和原型模式两种方式。

结构型模式

适配器模式(Adapter)

效果

将一个类的接口转换成客户但愿的另外一个接口,使本来因为接口不兼容而不能一块儿工做的那些类能够在一块儿工做。

核心角色

1. 目标接口(Target):客户所指望的接口(接口、抽象类或具体类)。

2. 适配的类(Adaptee)。

3. 适配器(Adapter):经过包装适配的类,把原接口转换成目标接口。

分类

1. 使用继承实现:Adapter继承Adaptee。

2. 使用关联实现:Adapter持有Adaptee的引用,Adapter能够继承其余类,更灵活。

代码(使用继承)

1. Target.java

1 public interface Target {
2 
3     void handleRequest();
4     
5 }
View Code

2. Adaptee.java

1 public class Adaptee {
2 
3     public void request() {
4         System.out.println("处理请求!");
5     }
6     
7 }
View Code

3. Adapter.java

1 public class Adapter extends Adaptee implements Target {
2     
3     @Override
4     public void handleRequest() {
5         request();
6     }
7 
8 }
View Code

4. Client.java

 1 public class Client {
 2     
 3     public void execute(Target target) {
 4         target.handleRequest();
 5     }
 6 
 7     public static void main(String[] args) {
 8         Target target = new Adapter();
 9         new Client().execute(target);
10     }
11 
12 }
View Code

代码(使用关联)

1. Target.java

1 public interface Target {
2 
3     void handleRequest();
4     
5 }
View Code

2. Adaptee.java

1 public class Adaptee {
2 
3     public void request() {
4         System.out.println("处理请求!");
5     }
6     
7 }
View Code

3. Adapter.java

 1 public class Adapter implements Target {
 2     
 3     // 使用关联更灵活,这样适配器能够继承其余类
 4     private Adaptee adaptee;
 5 
 6     public Adapter(Adaptee adaptee) {
 7         this.adaptee = adaptee;
 8     }
 9 
10     @Override
11     public void handleRequest() {
12         adaptee.request();
13     }
14 
15 }
View Code

4. Client.java

 1 public class Client {
 2     
 3     public void execute(Target target) {
 4         target.handleRequest();
 5     }
 6 
 7     public static void main(String[] args) {
 8         Target target = new Adapter();
 9         new Client().execute(target);
10     }
11 
12 }
View Code

应用场景

1. 作旧系统改造和升级。

2. java.io.InputStreamReader(InputStream)。

3. java.io.OutputStreamWriter(OutputStream)。

代理模式(Proxy)

效果

1. 经过代理,控制对对象的访问。

2. 能够详细控制访问某个(某类)对象的方法,在调用方法前作前置处理,调用方法后作后置处理(即APO的微观实现)。

3. AOP(Aspect Oriented Programming,面向切面编程)的核心实现机制。

核心角色

1. 抽象角色:定义代理角色和真实角色的公共对外方法。

2. 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

3. 代理角色:实现抽象角色,是真实角色的代理,经过真实角色的业务逻辑方法来实现抽象方法,并能够附加本身操做。

分类

1. 静态代理(静态定义代理类)。

2. 动态代理(动态定义代理类):

    a) JDK自带的动态代理(java.lang.reflect.Proxy动态生成代理类和对象,java.lang.reflect.InvocationHandler经过invoke()方法实现访问真实角色);

    b) javaassist字节码操做库实现;

    c) CGLIB;

    d) ASM(底层使用指令,可维护性较差)。

代码(静态代理)

1. Star.java

 1 public interface Star {
 2 
 3     void confer();
 4     
 5     void signContract();
 6     
 7     void bookTicket();
 8     
 9     void sing();
10     
11     void collectMoney();
12     
13 }
View Code

2. RealStar.java

 1 public class RealStar implements Star {
 2 
 3     @Override
 4     public void confer() {
 5         System.out.println("RealStar.confer()");
 6     }
 7 
 8     @Override
 9     public void signContract() {
10         System.out.println("RealStar.signContract()");
11     }
12 
13     @Override
14     public void bookTicket() {
15         System.out.println("RealStar.bookTicket()");
16     }
17 
18     @Override
19     public void sing() {
20         System.out.println("RealStar.sing()");
21     }
22 
23     @Override
24     public void collectMoney() {
25         System.out.println("RealStar.collectMoney()");
26     }
27 
28 }
View Code

3. ProxyStar.java

 1 public class ProxyStar implements Star {
 2     
 3     private Star realStar;
 4     
 5     public ProxyStar(Star realStar) {
 6         this.realStar = realStar;
 7     }
 8 
 9     @Override
10     public void confer() {
11         System.out.println("ProxyStar.confer()");
12     }
13 
14     @Override
15     public void signContract() {
16         System.out.println("ProxyStar.signContract()");
17     }
18 
19     @Override
20     public void bookTicket() {
21         System.out.println("ProxyStar.bookTicket()");
22     }
23 
24     @Override
25     public void sing() {
26         realStar.sing();
27     }
28 
29     @Override
30     public void collectMoney() {
31         System.out.println("ProxyStar.collectMoney()");
32     }
33 
34 }
View Code

4. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         RealStar realStar = new RealStar();
 5         ProxyStar proxyStar = new ProxyStar(realStar);
 6         proxyStar.confer();
 7         proxyStar.signContract();
 8         proxyStar.bookTicket();
 9         proxyStar.sing();
10         proxyStar.collectMoney();
11     }
12 
13 }
View Code

代码(动态代理)

1. Star.java

 1 public interface Star {
 2 
 3     void confer();
 4     
 5     void signContract();
 6     
 7     void bookTicket();
 8     
 9     void sing();
10     
11     void collectMoney();
12     
13 }
View Code

2. RealStar.java

 1 public class RealStar implements Star {
 2 
 3     @Override
 4     public void confer() {
 5         System.out.println("RealStar.confer()");
 6     }
 7 
 8     @Override
 9     public void signContract() {
10         System.out.println("RealStar.signContract()");
11     }
12 
13     @Override
14     public void bookTicket() {
15         System.out.println("RealStar.bookTicket()");
16     }
17 
18     @Override
19     public void sing() {
20         System.out.println("RealStar.sing()");
21     }
22 
23     @Override
24     public void collectMoney() {
25         System.out.println("RealStar.collectMoney()");
26     }
27 
28 }
View Code

3. StarHandler.java

 1 import java.lang.reflect.InvocationHandler;
 2 import java.lang.reflect.Method;
 3 
 4 public class StarHandler implements InvocationHandler {
 5     
 6     private Star realStar;
 7 
 8     public StarHandler(Star realStar) {
 9         this.realStar = realStar;
10     }
11 
12     @Override
13     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
14         switch (method.getName()) {
15         case "confer":
16             System.out.println("ProxyStar.confer()");
17             break;
18         case "signContract":
19             System.out.println("ProxyStar.signContract()");
20             break;
21         case "bookTicket":
22             System.out.println("ProxyStar.bookTicket()");
23             break;
24         case "sing":
25             method.invoke(realStar, args);
26             break;
27         case "collectMoney":
28             System.out.println("ProxyStar.collectMoney()");
29             break;
30         }
31         
32         return null;
33     }
34 
35 }
View Code

4. Client.java

 1 import java.lang.reflect.Proxy;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) {
 6         Star realStar = new RealStar();
 7         StarHandler handler = new StarHandler(realStar);
 8         Star proxyStar = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] { Star.class }, handler);
 9         proxyStar.confer();
10         proxyStar.signContract();
11         proxyStar.bookTicket();
12         proxyStar.sing();
13         proxyStar.collectMoney();
14     }
15 
16 }
View Code

应用场景

1. 安全代理:屏蔽对真实角色的直接访问。

2. 远程代理:经过代理类处理远程方法调用(RMI)。

3. 延迟代理:先加载轻量级代理对象,真正须要时再加载真实对象。

桥接模式(Bridge)

效果

1. 处理多层继承结构、处理多维变化的场景,将各个维度设计成独立的继承结构,使各个维度能够独立的扩展在抽象层创建关联。

2. 以商场系统中的电脑分类为例,多层继承不利于扩展性(类个数膨胀问题):

    a) 若是要增长一个新的电脑类型智能手机,则要增长各个品牌下面的类。

    b) 若是要增长一个新的品牌,也要增长各类电脑类型的类。

3. 违反单一职责原则:好比一个联想笔记本,有两个引发这个类变化的缘由。

4. 桥接模式将电脑拆分为类型和品牌两个维度。

代码

1. Computer.java

 1 public abstract class Computer {
 2 
 3     protected Brand brand;
 4 
 5     public Computer(Brand brand) {
 6         this.brand = brand;
 7     }
 8     
 9     public abstract void run();
10     
11 }
12 
13 class Desktop extends Computer {
14 
15     public Desktop(Brand brand) {
16         super(brand);
17     }
18 
19     @Override
20     public void run() {
21         System.out.println(brand.getName() + "台式机运行!");
22     }
23     
24 }
25 
26 class Laptop extends Computer {
27 
28     public Laptop(Brand brand) {
29         super(brand);
30     }
31 
32     @Override
33     public void run() {
34         System.out.println(brand.getName() + "笔记本运行!");
35     }
36     
37 }
View Code

2. Brand.java

 1 public interface Brand {
 2 
 3     String getName();
 4     
 5 }
 6 
 7 class Lenovo implements Brand {
 8     
 9     @Override
10     public String getName() {
11         return "联想";
12     }
13     
14 }
15 
16 class Dell implements Brand {
17 
18     @Override
19     public String getName() {
20         return "戴尔";
21     }
22     
23 }
View Code

3. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Brand brand = new Lenovo();
5         Computer computer = new Laptop(brand);
6         computer.run();
7     }
8 
9 }
View Code

应用场景

1. JDBC驱动程序。

2. 银行日志管理。

    a) 格式分类:操做日志、交易日志、异常日志。

    b) 距离分类:本地记录日志、异地记录日志。

3. 人力资源系统的奖金计算模块。

    a) 奖金分类:我的奖金、团体奖金、激励奖金。

    b) 部门分类:人事部门、销售部门、研发部门。

4. OA系统的消息处理。

    a) 业务类型:普通消息、加急消息、特急消息。

    b) 发送消息方式:系统内消息、手机短信、邮件。

组合模式(Composite)

效果

1. 把部分和整理的关系用树形结构表示,从而使客户端可使用统一方式处理部分对象和总体对象。

2. 组合模式为处理树形结构提供了完美的解决方案,描述了如何将容器和叶子进行递归组合,使得用户在使用时能够一致性的对待容器和叶子。

核心角色

1. 抽象构件角色(Component):定义了叶子和容器构件的共同点。

2. 叶子构件角色(Leaf):无子节点。

3. 容器构件角色(Composite):有容器特征,能够包含子节点。

代码

Component.java

 1 import java.util.List;
 2 
 3 public interface Component {
 4 
 5     void operation();
 6     
 7 }
 8 
 9 interface Leaf extends Component {
10     
11 }
12 
13 interface Composite extends Component {
14     
15     void add(Component child);
16     
17     void remove(Component child);
18     
19     List<Component> getChildren();
20     
21 }
View Code

代码(杀毒举例)

1. AbstractFile.java

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public interface AbstractFile {
 5 
 6     void killVirus();
 7     
 8 }
 9 
10 class File implements AbstractFile {
11     
12     private String name;
13 
14     public File(String name) {
15         this.name = name;
16     }
17 
18     @Override
19     public void killVirus() {
20         System.out.println(name + " 文件杀毒!");
21     }
22     
23 }
24 
25 class Folder implements AbstractFile {
26     
27     private String name;
28     private List<AbstractFile> children = new ArrayList<>();
29 
30     public Folder(String name) {
31         this.name = name;
32     }
33     
34     public void add(AbstractFile child) {
35         children.add(child);
36     }
37     
38     public void remove(AbstractFile child) {
39         children.remove(child);
40     }
41 
42     @Override
43     public void killVirus() {
44         for (AbstractFile child : children) {
45             child.killVirus();
46         }
47         System.out.println(name + " 文件夹杀毒!");
48     }
49     
50 }
View Code

2. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Folder myDocument = new Folder("个人文档");
 5         myDocument.add(new File("Client.java"));
 6         myDocument.add(new File("index.php"));
 7         myDocument.add(new File("老师.avi"));
 8         Folder book = new Folder("图书");
 9         book.add(new File("设计模式.pdf"));
10         book.add(new File("Hadoop权威指南.pdf"));
11         myDocument.add(book);
12         myDocument.killVirus();
13     }
14 
15 }
View Code

应用场景

1. 操做系统的资源管理器。

2. GUI的容器层次图。

3. XML文件解析。

4. OA系统的组织结构处理。

5. JUnit单元测试框架:Test接口(抽象)、TestCase(叶子)、TestUnit(容器)。

装饰器模式(Decorator)

效果

1. 又称包装器模式(Wrapper)。

2. 动态的为一个对象增长新的功能。

3. 装饰器模式是一种用于代替继承的技术,无须经过继承增长子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

4. 装饰器模式下降系统的耦合度,能够动态的增长或删除对象的职责,并使得须要装饰的具体构件类和具体装饰类能够独立变化,以便增长新的具体构件类和具体装饰类。

核心角色

1. 抽象构件角色(Component):具体构件角色和装饰角色有相同的接口,客户端可以以与具体构件角色相同的方式同装饰角色交互。

2. 具体构件角色(ConcreteComponent)。

3. 装饰角色(Decorator):持有一个抽象构件角色引用,接收全部客户端请求,并把这些请求转发给具体装饰角色。

4. 具体装饰角色(ConcreteDecorator):给构件增长新功能。

代码

1. ICar.java

 1 public interface ICar {
 2 
 3     void move();
 4     
 5 }
 6 
 7 // 具体构建角色
 8 class Car implements ICar {
 9 
10     @Override
11     public void move() {
12         System.out.println("陆地上跑!");
13     }
14     
15 }
16 
17 // 装饰器角色
18 abstract class SuperCar implements ICar {
19 
20     private ICar car;
21     
22     public SuperCar(ICar car) {
23         this.car = car;
24     }
25 
26     public abstract void move();
27     
28 }
29 
30 class FlyCar extends SuperCar {
31 
32     public FlyCar(ICar car) {
33         super(car);
34     }
35     
36     @Override
37     public void move() {
38         super.move();
39         fly();
40     }
41     
42     public void fly() {
43         System.out.println("天上飞!");
44     }
45     
46 }
47 
48 class WaterCar extends SuperCar {
49     
50     public WaterCar(ICar car) {
51         super(car);
52     }
53 
54     @Override
55     public void move() {
56         super.move();
57         swim();
58     }
59     
60     public void swim() {
61         System.out.println("水上游!");
62     }
63     
64 }
65 
66 class AICar extends SuperCar {
67 
68     public AICar(ICar car) {
69         super(car);
70     }
71 
72     @Override
73     public void move() {
74         super.move();
75         autoMove();
76     }
77     
78     public void autoMove() {
79         System.out.println("自动跑!");
80     }
81     
82 }
View Code

2. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Car car = new Car();
 5         car.move();
 6         
 7         // 陆地上跑 + 天上飞
 8         FlyCar flyCar = new FlyCar(car);
 9         flyCar.move();
10         
11         // 陆地上跑  + 水上游
12         WaterCar waterCar = new WaterCar(car);
13         waterCar.move();
14         
15         // 陆地上跑  + 自动跑
16         AICar aiCar = new AICar(car);
17         aiCar.move();
18         
19         // 陆地上跑 + 天上飞 + 水上游
20         WaterCar flyWaterCar = new WaterCar(flyCar);
21         flyWaterCar.move();
22         
23         // 陆地上跑 + 天上飞 + 水上游 + 自动跑
24         AICar aiFlyWaterCar = new AICar(flyWaterCar);
25         aiFlyWaterCar.move();
26     }
27 
28 }
View Code

应用场景

1. IO的InputStream、OutputStream、Reader、Writer的设计。

2. Servlet API的request对象的默认实现类HttpServletRequestWrapper。

外观模式(Facade)

效果

1. 为子系统提供统一的入口。封装子系统的复杂性,便于客户端调用。

2. 迪米特法则:一个软件实体应当尽量少地与其余实体发生相互做用。

代码

1. Tea.java

1 public interface Tea {
2 
3     String getName();
4     
5     void drink();
6     
7 }
View Code

2. WaitressFacade.java

  1 public class WaitressFacade {
  2 
  3     public Tea makeTea(String teaName) {
  4         Water water = new Water("农夫山泉", 100.0);
  5         Tea tea = null;
  6         switch (teaName) {
  7         case "西湖龙井":
  8             tea = new XiHuLongJing();
  9             break;
 10         case "碧螺春":
 11             tea = new BiLuoChun();
 12             break;
 13         case "铁观音":
 14             tea = new TieGuanYin();
 15             break;
 16         default:
 17             return null;
 18         }
 19         TeaSet teaSet = new TeaSet();
 20         teaSet.cleanTeaSet(water);
 21         teaSet.addTea(tea);
 22         teaSet.cleanTea(water);
 23         teaSet.makeTea(water);
 24         return tea;
 25     }
 26     
 27 }
 28 
 29 class Water {
 30     
 31     private String name;
 32     
 33     private Double temperature;
 34 
 35     public Water(String name, Double temperature) {
 36         this.name = name;
 37         this.temperature = temperature;
 38     }
 39 
 40     public String getName() {
 41         return name;
 42     }
 43 
 44     public Double getTemperature() {
 45         return temperature;
 46     }
 47 
 48 }
 49 
 50 class TeaSet {
 51     
 52     private Tea tea;
 53     
 54     public void cleanTeaSet(Water water) {
 55         System.out.println("使用" + water.getTemperature() + "°的" + water.getName() + "烫洗茶具!");
 56     }
 57     
 58     public void addTea(Tea tea) {
 59         System.out.println("投入" + tea.getName() + "!");
 60         this.tea = tea;
 61     }
 62     
 63     public void cleanTea(Water water) {
 64         System.out.println("使用" + water.getTemperature() + "°的" + water.getName() + "洗茶!");
 65     }
 66     
 67     public Tea makeTea(Water water) {
 68         System.out.println("使用" + water.getTemperature() + "°的" + water.getName() + "泡茶!");
 69         return tea;
 70     }
 71     
 72 }
 73 
 74 class XiHuLongJing implements Tea {
 75     
 76     @Override
 77     public String getName() {
 78         return "西湖龙井";
 79     }
 80 
 81     @Override
 82     public void drink() {
 83         System.out.println("品" + getName() + "!");
 84     }
 85     
 86 }
 87 
 88 class BiLuoChun implements Tea {
 89     
 90     @Override
 91     public String getName() {
 92         return "洞庭碧螺春";
 93     }
 94     
 95     @Override
 96     public void drink() {
 97         System.out.println("品" + getName() + "!");
 98     }
 99     
100 }
101 
102 class TieGuanYin implements Tea {
103 
104     @Override
105     public String getName() {
106         return "安溪铁观音";
107     }
108     
109     @Override
110     public void drink() {
111         System.out.println("品" + getName() + "!");
112     }
113     
114 }
View Code

3. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         WaitressFacade waitressFacade = new WaitressFacade();
5         Tea tea = waitressFacade.makeTea("铁观音");
6         tea.drink();
7     }
8 
9 }
View Code

应用场景

1. 频率很高,到处用到。

2. JDBC封装后的DbUtils类。

3. Hibernate提供的工具类。

4. Spring JDBC工具类等。

享元模式(FlyWeight)

效果

1. 享元模式以共享的方式高效地支持大量细粒度对象的重用。

    a) 内存属于稀缺资源,不要随便浪费。若是有不少个彻底相同或类似的对象,咱们能够经过享元模式节省内存。

    b) 用时间换取空间。

2. 享元对象能作到共享的关键是区分了内部状态和外部状态。

    a) 内部状态:能够共享,不会随环境变化而变化。

    b) 外部状态:不能够共享,会随环境变化而变化。

核心角色

1. 享元工厂类(FlyWeightFactory):建立并管理享元对象,享元池通常设计成键值对。

2. 抽象享元类(FlyWeight):一般是一个接口或抽象类,声明公共方法向外界提供对象的内部状态、设置外部状态。

3. 具体享元类(ConcreteFlyWeight):为内部状态提供成员变量进行存储。

4. 非共享享元类(UnsharedConcreteFlyWeight):不能被共享的子类能够设计为非共享享元类。

代码

1. ChessFlyWeight.java

1 // 抽象享元类
2 public interface ChessFlyWeight {
3 
4     String getColor();
5     
6     void display(Position position);
7     
8 }
View Code

2. Position.java

 1 // 非共享享元类
 2 public class Position {
 3 
 4     private int x;
 5     
 6     private int y;
 7 
 8     public Position(int x, int y) {
 9         this.x = x;
10         this.y = y;
11     }
12 
13     public int getX() {
14         return x;
15     }
16 
17     public int getY() {
18         return y;
19     }
20 
21 }
View Code

3. ConcreteChess.java

 1 // 具体享元类
 2 public class ConcreteChess implements ChessFlyWeight {
 3     
 4     private String color;
 5 
 6     public ConcreteChess(String color) {
 7         this.color = color;
 8     }
 9     
10     @Override
11     public String getColor() {
12         return color;
13     }
14 
15     @Override
16     public void display(Position position) {
17         System.out.println("显示:颜色" + color + ",位置(" + position.getX() + "," + position.getY() + ")!");
18     }
19 
20 }
View Code

4. ChessFactory.java

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 
 4 // 享元工厂类
 5 public class ChessFactory {
 6 
 7     private static Map<String, ChessFlyWeight> chesses = new HashMap<>();
 8     
 9     public static ChessFlyWeight getChess(String color) {
10         ChessFlyWeight chess = chesses.get(color);
11         if (chess != null) {
12             return chess;
13         }
14         chess = new ConcreteChess(color);
15         chesses.put(color, chess);
16         return chess;
17     }
18     
19 }
View Code

5. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         ChessFlyWeight chess1 = ChessFactory.getChess("黑");
 5         ChessFlyWeight chess2 = ChessFactory.getChess("黑");
 6         System.out.println(chess1 == chess2);
 7         
 8         chess1.display(new Position(10, 20));
 9         chess1.display(new Position(20, 10));
10     }
11 
12 }
View Code

应用场景

1. 享元模式因为共享的特性,能够应用与任何“池”,好比线程池、数据库链接池。

2. String类的设计。

行为型模式

责任链模式(Chain of Resposibility)

效果

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

2. 请假条审批过程:天数小于3天,主任审批;大于等于3天,小于10天,经理审批;大于等于10天,小于30天,总经理审批;大于等于30天,拒绝。

核心角色

1. 责任链既能够经过LinkedList实现,也能够经过ArrayList实现。

2. 可事先定义好责任链存储到配置文件或数据库。

代码

1. LeaveRequest.java

 1 public class LeaveRequest {
 2 
 3     private String name;
 4     
 5     private int leaveDays;
 6     
 7     private String reason;
 8 
 9     public LeaveRequest(String name, int leaveDays, String reason) {
10         this.name = name;
11         this.leaveDays = leaveDays;
12         this.reason = reason;
13     }
14 
15     public String getName() {
16         return name;
17     }
18 
19     public int getLeaveDays() {
20         return leaveDays;
21     }
22 
23     public String getReason() {
24         return reason;
25     }
26 
27 }
View Code

2. Leave.java

 1 public abstract class Leader {
 2 
 3     protected String name;
 4     
 5     protected Leader nextLeader;
 6 
 7     public Leader(String name) {
 8         this.name = name;
 9     }
10 
11     public void setNextLeader(Leader nextLeader) {
12         this.nextLeader = nextLeader;
13     }
14     
15     public abstract void handleRequest(LeaveRequest leaveRequest);
16     
17 }
18 
19 class Director extends Leader {
20 
21     public Director(String name) {
22         super(name);
23     }
24 
25     @Override
26     public void handleRequest(LeaveRequest leaveRequest) {
27         if (leaveRequest.getLeaveDays() < 3) {
28             System.out.println("主任" + name + "审批经过!");
29         } else if (nextLeader != null) {
30             nextLeader.handleRequest(leaveRequest);
31         }
32     }
33     
34 }
35 
36 class Manager extends Leader {
37     
38     public Manager(String name) {
39         super(name);
40     }
41     
42     @Override
43     public void handleRequest(LeaveRequest leaveRequest) {
44         if (leaveRequest.getLeaveDays() < 10) {
45             System.out.println("经理" + name + "审批经过!");
46         } else if (nextLeader != null) {
47             nextLeader.handleRequest(leaveRequest);
48         }
49     }
50     
51 }
52 
53 class GeneralManager extends Leader {
54 
55     public GeneralManager(String name) {
56         super(name);
57     }
58 
59     @Override
60     public void handleRequest(LeaveRequest leaveRequest) {
61         if (leaveRequest.getLeaveDays() < 30) {
62             System.out.println("总经理" + name + "审批经过!");
63         } else {
64             System.out.println("不经过!");
65         }
66     }
67     
68 }
View Code

3. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Leader director = new Director("张三");
 5         Leader manager = new Manager("李四");
 6         Leader generalManager = new GeneralManager("王五");
 7         director.setNextLeader(manager);
 8         manager.setNextLeader(generalManager);
 9         
10         LeaveRequest leaveRequest = new LeaveRequest("Tom", 5, "回英国老家。");
11         director.handleRequest(leaveRequest);
12     }
13 
14 }
View Code

应用场景

1. Java的异常捕获,try可对应多个catch,当第一个catch不匹配,则自动跳到第二个catch。

2. JavaScript的事件冒泡和捕获机制。

3. Servlet开发中,过滤器的链式处理。

迭代器模式(Iterator)

效果

1. 又称游标模式(Cursor)。

2. 提供一种能够遍历聚合对象的方式。

核心角色

1. 聚合对象(Aggregate):存储数据。

2. 迭代器(Iterator):遍历数据的算法,好比正序、倒序、随机等。

代码

1. Iterator.java

1 public interface Iterator {
2 
3     boolean hasNext();
4     
5     Object next();
6     
7 }
View Code

2. Aggregate.java

1 public interface Aggregate {
2 
3     void add(Object element);
4     
5     void remove(Object element);
6     
7     Iterator iterator();
8     
9 }
View Code

3. ConcreteAggregate.java

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class ConcreteAggregate implements Aggregate {
 5 
 6     private List<Object> list = new ArrayList<>();
 7     
 8     @Override
 9     public void add(Object element) {
10         list.add(element);
11     }
12 
13     @Override
14     public void remove(Object element) {
15         list.remove(element);
16     }
17 
18     @Override
19     public Iterator iterator() {
20         return new ConcreteAggregateIterator();
21     }
22     
23     // 定义成内部类,可直接访问外部类的属性
24     private class ConcreteAggregateIterator implements Iterator {
25 
26         private int cursor = -1;
27         
28         @Override
29         public boolean hasNext() {
30             return cursor < list.size() - 1;
31         }
32 
33         @Override
34         public Object next() {
35             cursor++;
36             return list.get(cursor);
37         }
38 
39     }
40 
41 }
View Code

4. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Aggregate aggregate = new ConcreteAggregate();
 5         aggregate.add("A");
 6         aggregate.add("B");
 7         aggregate.add("C");
 8         aggregate.add("D");
 9         aggregate.add("E");
10         
11         Iterator iterator = aggregate.iterator();
12         while (iterator.hasNext()) {
13             System.out.println(iterator.next());
14         }
15     }
16 
17 }
View Code

应用场景

JDK内置的迭代器。

中介者模式(Mediator)

效果

1. 若是一个系统中对象之间的联系呈现为网状结构,对象之间存在大量多对多关系,将致使关系及其复杂,这些对象称为“同事对象”。

2. 引入一个中介者对象,使各同事对象只跟中介者对象打交道,将复杂的网状结构解耦成星状结构。

3. 解耦多个同事对象之间的交互关系。每一个对象都持有中介者对象的引用,只跟中介者对象打交道。咱们经过中介者对象统一管理这些交互关系。

代码

1. 公司有总经理,各个部门有事情都通报给总经理,总经理再通知各个相关部门。总经理起到中介、协调做用。

2. Colleague.java

1 public interface Colleague {
2 
3     void selfAction();
4     
5     void outAction();
6     
7 }
View Code

3. Mediator.java

1 public interface Mediator {
2 
3     void register(String name, Colleague colleague);
4     
5     void command(String name);
6     
7 }
View Code

4. DevelopmentDepartment.java

 1 public class DevelopmentDepartment implements Colleague {
 2 
 3     private Mediator mediator;
 4     
 5     public DevelopmentDepartment(Mediator mediator) {
 6         this.mediator = mediator;
 7         mediator.register("研发部", this);
 8     }
 9 
10     @Override
11     public void selfAction() {
12         System.out.println("专心研发!");
13     }
14 
15     @Override
16     public void outAction() {
17         System.out.println("研发部向总经理汇报:须要资金支持!");
18         mediator.command("财务部");
19     }
20 
21 }
View Code

5. MarcketDepartment.java

 1 public class MarcketDepartment implements Colleague {
 2 
 3     private Mediator mediator;
 4     
 5     public MarcketDepartment(Mediator mediator) {
 6         this.mediator = mediator;
 7         mediator.register("市场部", this);
 8     }
 9 
10     @Override
11     public void selfAction() {
12         System.out.println("专心接项目");
13     }
14 
15     @Override
16     public void outAction() {
17         System.out.println("市场部向总经理汇报:须要资金支持!");
18     }
19 
20 }
View Code

6. FinacialDepartment.java

 1 public class FinacialDepartment implements Colleague {
 2 
 3     private Mediator mediator;
 4     
 5     public FinacialDepartment(Mediator mediator) {
 6         this.mediator = mediator;
 7         mediator.register("财务部", this);
 8     }
 9 
10     @Override
11     public void selfAction() {
12         System.out.println("专心数钱!");
13     }
14 
15     @Override
16     public void outAction() {
17         System.out.println("财务部向总经理汇报:钱太多,花不完!");
18         mediator.command("市场部");
19     }
20 
21 }
View Code

7. GeneralManager.java

 1 import java.util.HashMap;
 2 import java.util.Map;
 3 
 4 public class GeneralManager implements Mediator {
 5 
 6     private Map<String, Colleague> colleagues = new HashMap<>();
 7     
 8     @Override
 9     public void register(String name, Colleague colleague) {
10         colleagues.put(name, colleague);
11     }
12 
13     @Override
14     public void command(String name) {
15         colleagues.get(name).outAction();
16     }
17 
18 }
View Code

8. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         Mediator generalManager = new GeneralManager();
 5         Colleague developmentDepartment = new DevelopmentDepartment(generalManager);
 6         Colleague marcketDepartment = new MarcketDepartment(generalManager);
 7         Colleague finacialDepartment = new FinacialDepartment(generalManager);
 8         
 9         developmentDepartment.selfAction();
10         developmentDepartment.outAction();
11     }
12 
13 }
View Code

应用场景

1. MVC模式的C是中介者对象,M和V都和他打交道。

2. GUI中,多个组件之间交互,能够引入一个中介者对象(总体窗口对象或DOM对象)。

3. java.lang.reflect.Method#invoke()。

命令模式(Command)

效果

1. 又称“动做模式(Action)、事务模式(Transaction)。

2. 将一个请求封装成一个对象,从而使咱们可用不一样的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操做。

核心角色

1. 抽象命令类(Command)。

2. 具体命令类(ConcreteCommand)。

3. 调用者/请求者(Invoker):请求的发送者,经过命令对象来执行请求。调用者并不须要在设计时肯定接收者,而是在运行时,调用命令对象的execute(),间接调用接

收者的相关操做。

4. 接收者(Receiver):执行与请求相关的操做,具体实现对请求的业务处理。

代码

1. Command.java

1 public interface Command {
2 
3     // 实际中可设计多个方法
4     void execute();
5     
6 }
View Code

2. ConcreteCommand.java

 1 public class ConcreteCommand implements Command {
 2 
 3     private Receiver receiver;
 4     
 5     public ConcreteCommand(Receiver receiver) {
 6         this.receiver = receiver;
 7     }
 8 
 9     @Override
10     public void execute() {
11         // 可在执行先后作其余操做,好比记录日志
12         receiver.action();
13     }
14     
15 }
View Code

3. Invoker.java

 1 public class Invoker {
 2 
 3     // 也能够是多条命令,相似数据库事务中的多条命令
 4     private Command command;
 5 
 6     public Invoker(Command command) {
 7         this.command = command;
 8     }
 9     
10     public void call() {
11         command.execute();
12     }
13     
14 }
View Code

4. Receiver.java

1 public class Receiver {
2 
3     public void action() {
4         System.out.println("Receiver.action()");
5     }
6     
7 }
View Code

5. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Command command = new ConcreteCommand(new Receiver());
5         Invoker invoker = new Invoker(command);
6         invoker.call();
7     }
8 
9 }
View Code

应用场景

数据库事务机制的底层实现。

解释器模式(Interpreter)

效果

1. 不经常使用的设计模式。

2. 用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的编译器和解释器设计。

3. 尽可能不要使用解释器模式,后期维护很是麻烦。在项目中,可使用JRuby、Groovy、Java的JavaScript引擎来代替解释器,弥补Java语言不足。

应用场景

1. EL表达式的处理。

2. 正则表达式解释器。

3. SQL语法解释器。

4. 数学表达式解析器,如工具包Math Expression String Parser、Expression4J。

访问者模式(Visitor)

效果

1. 不经常使用的设计模式。

2. 对于存储在一个集合中的对象,他们可能具备不一样的类型(即便有一个公共的接口),对于该集合中的对象,能够接收一类称为访问者的对象来访问,不一样的访问者其访问方式也有所不一样。

3. 表示一个做用于某对象结构中各元素的操做,使咱们能够不在改变元素类的前提下定义做用于这些元素的新操做。

应用场景

1. XML文档解析器设计。

2. 编译器的设计。

3. 复杂集合对象的处理。

策略模式(Strategy)

效果

1. 策略模式对应于解决某一个问题的一个算法族,容许客户端从该算法族中任选一个算法解决问题,同时能够方便更换算法或添加新的算法。

2. 本质:分离算法,选择实现。

代码

1. 某个市场人员接到单后的报销策略(CRM系统的常见问题)。报价策略很复杂:

    a) 普通客户小批量报价;

    b) 普通客户大批量报价;

    c) 老客户小批量报价;

    d) 老客户大批量报价。

2. Strategy.java

1 public interface Strategy {
2 
3     double getPrice(double standardPrice);
4     
5 }
View Code

3. Context.java

 1 // 负责与具体的策略类交互,将客户端与算法分离
 2 public class Context {
 3 
 4     private Strategy strategy;
 5 
 6     public Context(Strategy strategy) {
 7         this.strategy = strategy;
 8     }
 9     
10     public void printPrice(double standardPrice) {
11         System.out.println(strategy.getPrice(standardPrice));
12     }
13     
14 }
View Code

4. NewCustomerFewStrategy.java

1 public class NewCustomerFewStrategy implements Strategy {
2 
3     @Override
4     public double getPrice(double standardPrice) {
5         System.out.println("不打折!");
6         return standardPrice;
7     }
8 
9 }
View Code

5. NewCustomerManyStrategy.java

1 public class NewCustomerManyStrategy implements Strategy {
2 
3     @Override
4     public double getPrice(double standardPrice) {
5         System.out.println("打九折!");
6         return standardPrice * 0.9;
7     }
8 
9 }
View Code

6. OldCustomerFewStrategy.java

1 public class OldCustomerFewStrategy implements Strategy {
2 
3     @Override
4     public double getPrice(double standardPrice) {
5         System.out.println("打八五折!");
6         return standardPrice * 0.85;
7     }
8 
9 }
View Code

7. OldCustomerManyStrategy.java

1 public class OldCustomerManyStrategy implements Strategy {
2 
3     @Override
4     public double getPrice(double standardPrice) {
5         System.out.println("打八折!");
6         return standardPrice * 0.8;
7     }
8 
9 }
View Code

8. Client.java

1 public class Client {
2 
3     public static void main(String[] args) {
4         Strategy strategy = new OldCustomerManyStrategy();    // 可经过配置生成
5         Context context = new Context(strategy);
6         context.printPrice(998);
7     }
8 
9 }
View Code

应用场景

1. Java的GUI编程,布局管理。

2. Spring框架的Resource接口,资源访问策略。

3. javax.servlet.http.HttpServlet#service()。

模板方法模式(Template Method)

效果

1. 经常使用的模式。

2. 模板方法定义一个操做的算法框架,将某些步骤延迟到子类中实现。这样,新的子类能够在不改变算法结构的前提下,从新定义该算法的某些特定步骤。

代码

1. BankTemplateMethod.java

 1 public abstract class BankTemplateMethod {
 2     
 3     protected void takeNumber() {
 4         System.out.println("取号!");
 5     }
 6 
 7     protected void waitInLine() {
 8         System.out.println("排队!");
 9     }
10     
11     // 钩子方法/回调方法:办理具体业务
12     protected abstract void transaction();
13     
14     protected void evaluate() {
15         System.out.println("评分!");
16     }
17     
18     // 模板方法
19     public final void process() {
20         takeNumber();
21         waitInLine();
22         transaction();
23         evaluate();
24     }
25     
26 }
View Code

2. DrawMoney.java

1 public class DrawMoney extends BankTemplateMethod {
2 
3     @Override
4     protected void transaction() {
5         System.out.println("取款!");
6     }
7 
8 }
View Code

3. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         BankTemplateMethod drawMoney = new DrawMoney();
 5         drawMoney.process();
 6         
 7         // 匿名内部类实现
 8         new BankTemplateMethod() {
 9 
10             @Override
11             protected void transaction() {
12                 System.out.println("存款!");
13             }
14             
15         }.process();;
16     }
17 
18 }
View Code

应用场景

1. 各框架、类库都有模板方法。

2. 数据库访问的封装。

3. JUnit单元测试。

4. Servlet的doGet()和doPost()方法调用。

5. Spring的JDBCTemplate、HibernateTemplate。

状态模式(State)

效果

1. 用于解决系统中复杂对象的状态转换以及不一样状态下行为的封装问题。

2. 酒店系统中,房间的状态变化。

核心角色

1. 上下文类(Context):环境类中维护一个State对象,定义了当前的状态。

2. 抽象状态类(State)。

3. 具体状态类(ConcreteState):每个类封装了一个状态对应的行为。

代码

1. State.java

1 public interface State {
2 
3     void handle();
4     
5 }
View Code

2. RoomContext.java

 1 public class RoomContext {
 2 
 3     private State state;
 4 
 5     public State getState() {
 6         return state;
 7     }
 8 
 9     public void setState(State state) {
10         this.state = state;
11         state.handle();
12     }
13     
14 }
View Code

3. FreeState.java

1 public class FreeState implements State {
2 
3     @Override
4     public void handle() {
5         System.out.println("退出房间!");
6     }
7 
8 }
View Code

4. BookedState.java

1 public class BookedState implements State {
2 
3     @Override
4     public void handle() {
5         System.out.println("预约房间!");
6     }
7 
8 }
View Code

5. CheckedInState.java

1 public class CheckedInState implements State {
2 
3     @Override
4     public void handle() {
5         System.out.println("入住房间!");
6     }
7 
8 }
View Code

6. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         RoomContext context = new RoomContext();
 5         context.setState(new FreeState());
 6         context.setState(new BookedState());
 7         context.setState(new CheckedInState());
 8     }
 9 
10 }
View Code

应用场景

1. 银行系统的帐号状态管理。

2. OA系统的公文状态管理。

3. 酒店系统的房间状态管理。

4. 线程对象各状态之间的切换。

观察者模式(Observer)

效果

1. 观察者模式用于1:N的消息通知。

2. 当目标对象(Subject或Observable)的状态变化(消息发布)时,他及时告知一系列观察者对象(Observer),令他们作出相应(消息订阅)。

3. 通知观察者的方式:

    a) 推:每次都会把消息以广播方式发送给全部观察者,全部观察者只能被动接收。

    b) 拉:观察者只要知道有变化便可,何时获取消息、获取什么内容,都由观察者自主决定。

代码

1. Subject.java

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public abstract class Subject {
 5 
 6     private List<Observer> observers = new ArrayList<>();
 7     
 8     public void subscribe(Observer observer) {
 9         observers.add(observer);
10     }
11     
12     public void unsubscribe(Observer observer) {
13         observers.remove(observer);
14     }
15     
16     public void notifyAllObservers() {
17         for (Observer observer : observers) {
18             observer.update(this);
19         }
20     }
21     
22 }
View Code

2. ConcreteSubject.java

 1 public class ConcreteSubject extends Subject {
 2 
 3     private int state;
 4 
 5     public int getState() {
 6         return state;
 7     }
 8 
 9     public void setState(int state) {
10         this.state = state;
11         notifyAllObservers();
12     }
13     
14 }
View Code

3. Observer.java

1 public interface Observer {
2 
3     void update(Subject subject);
4     
5 }
View Code

4. ConcreteObserver.java

 1 public class ConcreteObserver implements Observer {
 2     
 3     private String name;
 4 
 5     public ConcreteObserver(String name) {
 6         this.name = name;
 7     }
 8 
 9     @Override
10     public void update(Subject subject) {
11         System.out.println(name + "收到消息:state=" + ((ConcreteSubject) subject).getState());
12     }
13 
14 }
View Code

5. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         ConcreteSubject subject = new ConcreteSubject();
 5         Observer observer1 = new ConcreteObserver("张三");
 6         Observer observer2 = new ConcreteObserver("李四");
 7         Observer observer3 = new ConcreteObserver("王五");
 8         subject.subscribe(observer1);
 9         subject.subscribe(observer2);
10         subject.subscribe(observer3);
11         
12         subject.setState(1);
13         subject.setState(2);
14     }
15 
16 }
View Code

代码(基于JDK)

1. ConcreteSubject.java

 1 import java.util.Observable;
 2 
 3 public class ConcreteSubject extends Observable {
 4 
 5     private int state;
 6 
 7     public int getState() {
 8         return state;
 9     }
10 
11     public void setState(int state) {
12         this.state = state;
13         // 目标对象已变化
14         setChanged();
15         // 通知观察者
16         notifyObservers(state);
17     }
18     
19 }
View Code

2. ConcreteObserver.java

 1 import java.util.Observable;
 2 import java.util.Observer;
 3 
 4 public class ConcreteObserver implements Observer {
 5 
 6     private String name;
 7 
 8     public ConcreteObserver(String name) {
 9         this.name = name;
10     }
11     
12     @Override
13     public void update(Observable observable, Object arg) {
14         ConcreteSubject subject = (ConcreteSubject) observable;
15         System.out.println(name + "收到消息:" + arg);
16         System.out.println(name + "获取最新状态:" + subject.getState());
17     }
18 
19 }
View Code

3. Client.java

 1 import java.util.Observer;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) {
 6         ConcreteSubject subject = new ConcreteSubject();
 7         Observer observer1 = new ConcreteObserver("张三");
 8         Observer observer2 = new ConcreteObserver("李四");
 9         Observer observer3 = new ConcreteObserver("王五");
10         subject.addObserver(observer1);
11         subject.addObserver(observer2);
12         subject.addObserver(observer3);
13         
14         subject.setState(1);
15         subject.setState(2);
16     }
17 
18 }
View Code

应用场景

1. 聊天室,服务器转发给全部客户端。

2. 网络游戏多人联机对战,服务器将客户端的状态进行分发。

3. 邮件订阅。

4. Servlet编程,监听器的实现。

5. Android,广播机制。

6. 京东商城,群发某商品打折信息。

备忘录模式(Memento)

效果

保存某个对象内部状态的拷贝,之后能够将该对象恢复到原先状态。

核心角色

1. 源发器类(Originator):负责建立一个备忘录类,用以记录当前内部状态,并可以使用备忘录恢复内部状态。

2. 备忘录类(Memento):负责存储源发器类的内部状态,并可防止源发器类之外的其余对象访问备忘录类。

3. 负责人类(CareTaker):负责保存好备忘录,备忘点较多时,可用List或Stack存储。也能够持久化。

代码

1. Employee.java

 1 // 源发器类
 2 public class Employee {
 3 
 4     private String name;
 5     
 6     private int age;
 7     
 8     private double salary;
 9 
10     public Employee(String name, int age, double salary) {
11         this.name = name;
12         this.age = age;
13         this.salary = salary;
14     }
15     
16     // 备忘
17     public EmployeeMemento memento() {
18         return new EmployeeMemento(this);
19     }
20     
21     // 恢复
22     public void recover(EmployeeMemento employeeMemento) {
23         this.name = employeeMemento.getName();
24         this.age = employeeMemento.getAge();
25         this.salary = employeeMemento.getSalary();
26     }
27 
28     public String getName() {
29         return name;
30     }
31 
32     public void setName(String name) {
33         this.name = name;
34     }
35 
36     public int getAge() {
37         return age;
38     }
39 
40     public void setAge(int age) {
41         this.age = age;
42     }
43 
44     public double getSalary() {
45         return salary;
46     }
47 
48     public void setSalary(double salary) {
49         this.salary = salary;
50     }
51     
52     @Override
53     public String toString() {
54         return "name=" + name + ",age=" + age + ",salary=" + salary;
55     }
56     
57 }
View Code

2. EmployeeMemento.java

 1 public class EmployeeMemento {
 2 
 3     private String name;
 4 
 5     private int age;
 6 
 7     private double salary;
 8 
 9     public EmployeeMemento(Employee employee) {
10         this.name = employee.getName();
11         this.age = employee.getAge();
12         this.salary = employee.getSalary();
13     }
14 
15     public String getName() {
16         return name;
17     }
18 
19     public int getAge() {
20         return age;
21     }
22 
23     public double getSalary() {
24         return salary;
25     }
26     
27 }
View Code

3. EmployeeCareTaker.java

 1 import java.util.ArrayList;
 2 import java.util.List;
 3 
 4 public class EmployeeCareTaker {
 5 
 6     private List<EmployeeMemento> mementoes = new ArrayList<>();
 7     
 8     public void addMemento(EmployeeMemento mementoe) {
 9         mementoes.add(mementoe);
10     }
11     
12     public EmployeeMemento getMemento(int index) {
13         return mementoes.get(index);
14     }
15     
16     public EmployeeMemento getLastMemento() {
17         return getMemento(mementoes.size() - 1);
18     }
19     
20 }
View Code

4. Client.java

 1 public class Client {
 2 
 3     public static void main(String[] args) {
 4         EmployeeCareTaker careTaker = new EmployeeCareTaker();
 5         
 6         Employee employee = new Employee("张三", 18, 1000);
 7         System.out.println(employee);
 8         
 9         careTaker.addMemento(employee.memento());
10         employee.setAge(20);
11         employee.setSalary(3000);
12         System.out.println(employee);
13         careTaker.addMemento(employee.memento());
14         
15         employee.setAge(21);
16         System.out.println(employee);
17         
18         employee.recover(careTaker.getLastMemento());
19         System.out.println(employee);
20     }
21 
22 }
View Code

应用场景

1. 棋类游戏的悔棋。

2. 编辑软件的撤销操做。

3. 数据库的事务回滚操做。

4. Photoshop的历史版本记录。

 

做者:netoxi
出处:http://www.cnblogs.com/netoxi本文版权归做者和博客园共有,欢迎转载,未经赞成须保留此段声明,且在文章页面明显位置给出原文链接。欢迎指正与交流。

相关文章
相关标签/搜索