设计模式随笔

设计模式是什么?它是一套理论,由软件前辈们总结出来一套可以反复使用的经验,它可以提高代码的可重用性,增强系统可维护性,以及解决一系列复杂问题;设计模式是一把利剑,可以让你设计出强壮、稳定、高效的系统,并且自动预防未来业务变化对系统带来的影响,提高系统扩展性
首先专家门提出6大设计原则,但这6大设计原则仅仅是口号,真正工程落地要有详细的指导方法,所以就有了23种设计模式。

六大设计原则

原则 英文简写 描述信息
单一职责原则 SRP 接口、类职责划分明确保证职责单一,应该有且仅有一个原因引起类的变更
里氏替换原则 LSP 描述继承父子关系,所有引用基类地方必须能透明地使用子类的对象替换
依赖倒置原则 DIP 高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象
接口隔离原则 ISP 接口尽量细化,接口中的方法尽量少,仅仅暴露给客户端需要的接口
迪米特法则 LoD/LKP 一个对象应该对其他对象有最少了解(较少不必要的耦合)
开闭原则 OCP 软件实体应该对扩展开放,对修改关闭(最基础的原则,是其他原则的精神领袖)

设计模式分类

设计模式按照目的和作用范围有两种划分方式

  1. 按照目的,可分为创建型模式、结构型模式和行为型模式3种

    • 创建型模式:用于描述“怎样创建对象”,它的主要特点“将对象创建与使用分离”
    • 结构型模式:用于描述“如何将类或对象按照某种布局组成更大的结构”
    • 行为型模式:用于描述“类或对象之间怎样相互协调共同完成单个对象无法单独完成的任务”
  2. 按照作用范围,可分为类模式和对象模式2种

    • 类模式:用于处理类与子类间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了
    • 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性
    范围\目的 创建型模式 结构型模式 行为型模式
    类模式 工厂方法 适配器(类) 模板方法
    解释器
    对象模式 单例
    原型
    抽象工厂
    建造者
    代理
    适配器(对象)
    桥接
    装饰
    门面
    享元
    组合
    策略
    命令
    责任链
    状态
    观察者
    中介者
    迭代器
    访问者
    备忘录

常用设计模式介绍

单例模式

单例模式是一种比较简单的模式,指有且仅有一个实例对象,主要有以下两种饿汉和懒汉两种形式:

饿汉:线程安全,非懒加载

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

懒汉(DCL):线程安全,懒加载

public class Singleton {
    //volatile 创建对象半初始化过程 防止并发指令重排序 造成的极端问题
    private static volatile Singleton instance ;
    private Singleton(){}
    public static Singleton getInstance(){
        if(instance == null ){
            synchronized(Singleton.class){
                if(instance == null ){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

内部类形式:线程安全,懒加载

public class Singleton {
    private Singleton(){}
    //JVM保证单例 线程安全
    //加载外部类时候,内部类不会加载  懒加载
    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }
    private static class SingletonHolder{
        private final static Singleton INSTANCE = new Singleton();
    }
}

枚举形式:即能保证线程安全,又能防止序列化、反射等问题

public enum Singleton{
    INSTANCE;
    public Singleton getInstance(){
        return INSTANCE;
    }
}

单例有很多种模式,根据自己喜好灵活选择。

优点:单例模式只有一个实例,节省内存资源、减少系统性能开销

缺点:没有接口,扩展困难,对测试不友好(没有接口无法mock方式虚拟对象),与SRP冲突

使用场景:共享资源加载、访问等(一个类只允许有一个实例对象)

工厂方法

定义一个用于创建对象的接口,让子类决定实例化那一个类,工厂方法使一个类的实例化延迟到其子类。

工厂方法通用类图:

Product 抽象产品类

public abstract class Product{
    //产品类公共方法
    public void method1(){
        //TODO
    }
    //抽象方法,具体的产品实现
    public abstract void method2();
}

ConcreteProduct 具体产品类

//产品1
public class ConcreteProduct1 extends Product {
    public void method2(){
        //具体产品业务逻辑
    }
}
//产品2
public class ConcreteProduct2 extends Product {
    public void method2(){
        //具体产品业务逻辑
    }
}

Creator 抽象工厂类

public abstract class Creator{
    //创建一个产品对象
    public abstract <T extends Product> T createProduct(Class<T> c);
}

ConcreteCreator 具体工厂类

//具体工厂1
public class ConcreteCreator1 extends Creator{
   //创建一个产品对象
    public <T extends Product> T createProduct(Class<T> c){
        Product product = new ConcreteProduct1();
        return product;
    } 
}
//具体工厂2
public class ConcreteCreator2 extends Creator{
   //创建一个产品对象
    public <T extends Product> T createProduct(Class<T> c){
        Product product = new ConcreteProduct2();
        return product;
    } 
}
//通用工厂写法
public class CommonCreator extends Creator{
    public <T extends Product> T createProduct(Class<T> c){
        Product product = null;
        try{
            product = (Product)Class.forName(c.getName()).newInstance();
        }catch(Exception e){
            //异常处理
        }
        return (T)product;
    } 
}

另外,没有抽象或接口工厂,只有一个工厂类(一个工厂类生产多个具体产品),就对应简单工厂。

优点:良好封装性,代码结构清晰;屏蔽产品类,具体产品细节无需关注,面向产品接口;增加产品,只需增加对应工厂,易扩展

缺点:每增加一类产品,就需要扩展一个具体产品类和工厂类,随着产品增加多,类个数双倍增长,不易管理

使用场景:工厂方法模式使用场景比较多,类创建地方几乎都可以用到它,比如Sping就是一个大的bean生产工厂

抽象工厂

前面工厂方法中考虑的是一类产品的生产,如手机厂商只生产手机,电视厂商只生产电视,同种类型称为同级,工厂方法模式只考虑生产同等级产品;但是现实生活中许多工厂是综合型的工厂,能生产多个等级产品,比如手机厂商既能生产手机,又能生产电脑;抽象工厂模式考虑多等级产品生产,同一个具体的工厂所生产的位于不同等级的一组产品称为一个产品族。

抽象工厂定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂通用类图:

AbstractProductA:抽象产品A

public abstract class AbstractProductA{
    //产品类公共方法
    public void method1(){
        //TODO
    }
    //抽象方法,具体的产品实现
    public abstract void method2();
}

ProductA1:具体产品A1

public class ProductA1 extends AbstractProductA {
    //具体的产品实现
    public void method2(){
        System.out.println("具体产品A1实现方法");
    }
}

ProductA2:具体产品A2

public class ProductA2 extends AbstractProductA{
    //具体的产品实现
    public void method2(){
        System.out.println("具体产品A2实现方法");
    }
}

产品B与A类似,不在重复

Creator:抽象工厂类

public abstract class Creator{
	public abstract AbstractProductA createProductA();
    public abstract AbstractProductB createProductB();
}

Creator1:具体工厂类1

public class Creator1 extends Creator {
	public AbstractProductA createProductA(){
        return new ProductA1();
    }
    public AbstractProductB createProductB(){
        return new ProductB1();
    }
}

Creator2:具体工厂类2

public class Creator2 extends Creator {
	public AbstractProductA createProductA(){
        return new ProductA2();
    }
    public AbstractProductB createProductB(){
        return new ProductB2();
    }
}

M个产品应该有M个实现工厂类,每个具体的工厂类中实现不同产品族的生产

优点:产品等级扩展比较方便,只需增加对应产品和工厂实现类

缺点:产品族扩展比较困难,需要修改所有的工厂

横向(产品等级)扩展容易,纵向(产品族)扩展困难,纵向扩展不符合开闭原则

构造者模式

构造者模式又称为建造者模式,其主要功能是将一个复杂的对象的构建和表示进行分离,使得同样的构建过程可以创建不同的表示形式

构建者模式通用类图:

Product : 产品类

public class Product {
    public void doSomething(){
        //具体业务
    }
}

Builder : 抽象构建者

public abstract class Builder{
    //设置产品的不同部分,以获得不同的产品
    public abstract void setPart();
    //构建产品
    public abstract Product buildProduct();
}

ConcreteBuilder : 具体构建者

public class ConcreteBuilder extends Builder{
    Product product = new Product();
    //设置产品具体部分
    public void setPart(){
        
    }
    //构建产品
    public Product buildProduct(){
        return product;
    }
}

Director : 导演者

public class Director {
    private Builder builder = new ConcreteBuilder();
    //构建产品
    public Product getProduct(){
        builder.setPart();
        return build.buildProduct();
    }
}

构造者模式与工厂模式主要区分,构造者侧重产品的零件类型和装配过程

优点:具体装配过程有具体的构建者实现的,容易扩展;便于控制细节风险

缺点:产品必须有共同点,范围有限;若内部变化复杂,会有很对具体的建造者

使用场景:需要生成对象具有复杂的内部结构 ;内部属性相互依赖

代理模式

为其他对象提供一种代理以控制对这个对象的访问

代理模式类图如下:

Subject : 抽象主题角色

public interface Subject {
    public void request();
}

RealSubject : 具体主题角色

public class RealSubject implements Subject {
	public void request(){
		//具体实现
	}
}

Proxy : 代理类

public class Proxy implements Subject {
    private Subject subject ; 
    public Proxy(Subject subject){
        this.subject = subject;
    }
    public void request(){
        before();
        subject.request();
        after(); 
    }
    private void before(){
        //request前增加逻辑
    }
    private void after(){
        //request后增加逻辑
    }
}

优点:职责清晰、高扩展、智能化

缺点:增加一层代理对象,可能会造成请求速度的变慢

使用场景:远程代理、虚拟代理、防火墙等。(Spring AOP)

中介者模式

用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变他们之间的交互

中介者类图如下:

Mediator:抽象中介者角色

public abstract class Mediator {
   private ConcreteColleague1 colleague1;
   private ConcreteColleague2 colleague2;
   
    //抽象处理方法
   public abstract void doSomething1();
   public abstract void doSomething2();
}

ConcreteMediator:具体中介者角色

public class ConcreteMediator extends Mediator{
    //具体处理方法
   public void doSomething1(){
       super.colleague1.selfMethod1();
   }
    //具体处理方法
   public void doSomething2(){
       super.colleague2.selfMethod2();
   }
}

Colleague:抽象同事角色

public abstract class Colleague {
    private Mediator mediator;
}

ConcreteColleague:具体同事角色

public class ConcreteColleague1 extends Colleague {
    public void selfMethod1(){
        //处理自己的业务逻辑
    }
    public void dependMethod1(){
        super.mediator.doSomething1();
    }
}
public class ConcreteColleague2 extends Colleague {
    public void selfMethod2(){
        //处理自己的业务逻辑
    }
    public void dependMethod2(){
        super.mediator.doSomething2();
    }
}

优点:降低类的复杂度,将一对多转化成一对一;各个类之间解耦;符合迪米特原则

缺点:随着同事角色变多,变得复杂难以维护

使用场景:系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱

责任链模式

责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦

责任链类图:

责任链模式有两种:外部控制模式和节点控制模式

外部控制模式

通过外部调用的方式对链的各个节点调用进行控制,从而进行链的各个节点之间的切换

Handler : 抽象处理者

public abstract class Handler{
    //判断是否支持此Handler
    public abstract boolean support(Request request);
    //具体处理逻辑抽象方法
    public abstract void process(Request request);
}

ConcreteHandler : 具体处理者

public class ConcreteHandler1 extends Handler{
    //根据具体请求参数判断 
    public boolean support(Request request){
    	//TODO 
        return true;
    }
    //具体处理逻辑
    public void process(Request request){
        //TODO
    }
}

public class ConcreteHandler2 extends Handler{
    //根据具体请求参数判断 
    public boolean support(Request request){
    	//TODO 
        return true;
    }
    //具体处理逻辑
    public void process(Request request){
        //TODO
    }
}

Client : 客户端

public class HandlerChain{
    private List<Handler> handlers;
    public void process(Request request){
        //调用责任链
        for(Handler handler : handlers){
            if(handler.support(request)){
                handler.process(request);
            }
        }
    }
}

节点控制模式

Handler : 抽象处理者

public abstract class Handler{
    private Handler nextHandler;
    public final Response handleMessage(Request request){
        Response response = null;
        if(Objects.equals(this.getLevel(),request.getLevel())){
            response = process(request);
        }else{
            if(this.nextHandler != null ){
                response = this.nextHandler.handleMessage(request);
            }else{
                //其他逻辑
            }
        }
        return response;
    }
    public abstract Level getLevel();
    public abstract Response process(Request request);
}

ConcreteHandler : 具体处理者

public class ConcreteHandler1 extends Handler{
    //具体处理逻辑
    public Level getLevel(){
       	return Level.ONE;
    }
    public Response process(Request request){
        //执行具体逻辑
        return response;
    }
}

public class ConcreteHandler2 extends Handler{
    //具体处理逻辑
    public Level getLevel(){
       	return Level.TWO;
    }
    public Response process(Request request){
        //执行具体逻辑
        return response;
    }
}

优点:请求的发送者和接收者解耦;简化对象,使对象不需要知道调用链的结构;增强给对象指派职责的灵活性

缺点:不能保证请求一定被接受;调用链比较长时候,会影响性能,可能会造成循环调用;不容易排错

使用场景:有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定

装饰模式

装饰模式允许向一个现有的对象添加新的功能,同时又不改变其结构;主要解决扩展类继承引起子类膨胀的问题

装饰者模式类图:

Component : 抽象构建

public abstract class Component{
    public abstract void operate();
}

ConcreteComponent:具体构建

public class ConcreteComponent extends Component{
    public void operate(){
        System.out.println("具体组件...");
    }
}

Decorator:抽象装饰者

public abstract class Decorator extends Component{   
    private Component component;
    public void operate(){
        System.out.println("抽象装饰者...");
        component.operate();
    }
}

ConcreteDecorator:具体装饰者

public class ConcreteDecorator extends Decorator{   
    public void operate(){
        System.out.println("具体装饰者...");
        method1();
        super.operate();
    }
    private void method1(){
        //增加逻辑
    }
}

优点:装饰类和被装饰类可以独立发展,不会相互耦合,是继承的一种替代方式,可动态扩展一个实现类的功能

缺点:被多层装饰类修饰的时候,系统比较复杂

使用场景:扩展一个类的功能或者给一个类增加一个附加功能;增加的功能可撤销

策略模式

一个类的行为或其算法可以在运行时更改,可替代if...else

策略模式类图:

Context:封装角色

public class Context {
    //抽象策略
    private Strategy strategy;
    //封装后的策略方法
    public void doAnything(){
        this.strategy.doSomething();
    }
}

Strategy:抽象策略角色

public interface Strategy{
   public void doSomething(); 
}

ConcreteStrategy:具体策略角色

public class ConcreteStrategy1 implements Strategy{
    public void doSomething(){
        //具体策略1
    }
}
public class ConcreteStrategy2 implements Strategy{
    public void doSomething(){
        //具体策略2
    }
}

优点:算法可以自由切换;避免使用多条件判断;扩展性好

缺点:每个具体策略都对应一个类,策略类数量增多且对外暴露

使用场景:多个类只有在算法或行为上稍有不同的场景;算法需要切换场景;屏蔽算法规则的场景

适配器模式

将一个类的接口变换成客户端所期望的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作

适配器类图:

target:目标角色

public interface Target{
    public void doAnything();
}

Adaptee:源角色

public class Adaptee{
    public void doSomething(){
        
    } 
}

Adapter:适配器角色

public class Adapter extends Adaptee implements Target{
    public void doAnything(){
        super.doSomething();
    }
}

适配器Adapter,可以为抽象类,有具体的适配器

以上为类适配器模式;另外有对象适配器模式(类无法实现多继承),与类适配器模式差不对 如下:

public class Adapter implements Target{
    private Adaptee1 adaptee1 ;
    private Adaptee2 adaptee2 ;
    public void doAnything(){
        adaptee1.doSomething();
        adaptee2.doSomething();
    }
}

优点:可以让任何两个没有关联的类一起运行;提高了类的复用;增加了类的透明度;灵活性好

缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握

使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式

观察者模式

观察者模式也叫做发布订阅模式, 定义对象间一种以对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新

观察者模式类图:

Subject:抽象被观察者

public abstract class Subject{
    private List<Observer> observers = new ArrayList();
    public void attach(Observer o){
        observers.add(o);
    }
    public void detach(Observer o){
        observers.remove(o);
    }
    public void notify(){
        for(Observer o : observers){
            o.update();
        }
    }
}

ConcreteSubject:具体的被观察者

public class ConcreteSubject extends Subject {
    //具体的业务
    public void doSomething(){
        //TODO
        super.notify();
    }
}

Observer:抽象观察者

public interface Observer{
    //更新方法
    public void update();
}

ConcreteObserver:具体观察者

public class ConcreteSubject implements Observer{
    public void update(){
        //执行具体通知逻辑
    }
}

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:一个对象状态改变,会对其他对象产生影响,但是其他之前不确定,可以降低对象间的耦合。

访问者模式

封装一些作用于某种数据结构中的各元素操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作

访问者模式类图:

Visitor:抽象访问者

public interface IVisitor {
    //可以访问哪些对象
    public void visit(ConcreteElement1 el1);
    public void visit(ConcreteElement2 el2);
}

ConcreteVisitor:具体访问者

public class Visitor implements IVisitor {
	//访问el1元素
    public void visit(ConcreteElement1 el1) {
    	el1.doSomething();
    }
    //访问el2元素
    public void visit(ConcreteElement2 el2) {
    	el2.doSomething();
    }
}

Element:抽象元素

public abstract class Element {
    //定义业务逻辑
    public abstract void doSomething();
    //允许谁来访问
    public abstract void accept(IVisitor visitor);
}

ConcreteElement:具体元素

public class ConcreteElement1 extends Element{
    //完善业务逻辑
    public void doSomething(){
    	//业务处理
    }
    //允许那个访问者访问
    public void accept(IVisitor visitor){
    	visitor.visit(this);
    }
}
public class ConcreteElement2 extends Element{
    //完善业务逻辑
    public void doSomething(){
    	//业务处理
    }
    //允许那个访问者访问
    public void accept(IVisitor visitor){
    	visitor.visit(this);
    }
}

ObjectStruture:结构对象

public class ObjectStruture {
    //对象生成器, 这里通过一个工厂方法模式模拟
    public static Element createElement(){
        Random rand = new Random();
        if(rand.nextInt(100) > 50){
        	return new ConcreteElement1();
        }else{
        	return new ConcreteElement2();
        }
    }
}

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

门面模式

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。

门面模式提供一个高层次的接口, 使得子系统更易于使用 。

门面模式类图:

Facade:门面对象

public class Facade {
    //被委托的对象
    private ClassA a = new ClassA();
    private ClassB b = new ClassB();
    private ClassC c = new ClassC();
    //提供给外部访问的方法
    public void methodA(){
    	this.a.doSomethingA();
    } 
    public void methodB(){
        this.b.doSomethingB();
    }
    public void methodC(){
    	this.c.doSomethingC();
    }
}

Sub : 子系统对象

public class ClassA {
    public void doSomethingA(){
    //业务逻辑
    }
}
public class ClassB {
    public void doSomethingB(){
    //业务逻辑
    }
}
public class ClassC {
    public void doSomethingC(){
    //业务逻辑
    }
}

优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。

缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。

使用场景: 1、为复杂的模块或子系统提供外界访问的模块。 2、子系统相对独立。 3、预防低水平人员带来的风险。

桥梁模式

桥梁(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

桥梁模式类图:

Abstraction:抽象化角色

public abstract class Abstraction {
    //定义对实现化角色的引用
    private Implementor imp;
    //约束子类必须实现该构造函数
    public Abstraction(Implementor _imp){
        this.imp = _imp;
    }
    //自身的行为和属性
    public void request(){
    	this.imp.doSomething();
    }
    //获得实现化角色
    public Implementor getImp(){
    	return imp;
    }
}

Implementor:实现化角色

public interface Implementor {
    //基本方法
    public void doSomething();
    public void doAnything();
}

RefinedAbstraction:修正抽象化角色

public class RefinedAbstraction extends Abstraction {
    //覆写构造函数
    public RefinedAbstraction(Implementor _imp){
    	super(_imp);
    }
    //修正父类的行为
    @Override
    public void request(){
       
        super.request();
        super.getImp().doAnything();
    }
}

ConcreteImplementor:具体实现化角色

public class ConcreteImplementor1 implements Implementor{
    public void doSomething(){
    //业务逻辑处理
    }
    public void doAnything(){
    //业务逻辑处理
    }
}
public class ConcreteImplementor2 implements Implementor{
    public void doSomething(){
    	//业务逻辑处理
    }
    public void doAnything(){
    	//业务逻辑处理
    }
}

优点: 1、抽象和实现的分离。 2、优秀的扩展能力。 3、实现细节对客户透明。

缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

使用场景: 1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。 2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。

其他

模板方法 :定义算法的框架,具体每个算法实现延迟到子类实现

解释器模式:主要是用于语法解析

迭代器模式 :用于集合容器元素遍历,如Iterator

组合模式:主要用于描述整体和部分关系 比如 定义tree 由Composite 和 Leaf 组成

享元模式 :一般用于池化技术处理 ,如线程池、对象池、数据库连接池等

命令模式: 是命令的地方都可以使用此模式

备忘录模式:俗称“后悔药”, 记录副本数据,根据情况回退还原 如 “数据库事物”

状态模式 :类的行为是基于它的状态改变的;条件或分支语句替换

原型模式:用原型对象通过clone创建新对象,内存二进制拷贝,比new对象性能好,但是不会执行构造方法

posted @ 2020-10-05 12:51  mindy3250  阅读(139)  评论(0编辑  收藏  举报