设计模式记录

只有掌握设计模式,才能看懂开源框架代码
代码谁都会写,但是优秀的代码肯定不是

设计模式分类

  • 创建型模式:

    共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

  • 结构型模式:

共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  • 行为型模式:
共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

设计模式相关规则

一、找出应用中可能会变化的部分,把他们独立出来,不要和那些不需要变化代码在一起。
二、针对接口编程,而不是实现编程。
三、[多用组合,少用继承] 继承去复用不变化代码,接口去实现变化代码。
四、为了交互对象之间松耦合而努力。
五、开放关闭原则
 类应该对扩展开发,对修改关闭。在不修改代码情况下,对功能进行扩展。
 观察者模式就是,扩展主题功能,不需要向主题类里面添加代码只需要假如新的观察者。
 而装饰者模式就是完全遵守开关闭合选择。
 策略模式也可以实现开闭原则
 开闭原则的关键是抽象,当一个模块依赖的是抽象接口的时候,就可以对抽象接口进行扩展,这样就可以不改变现有的代码逻辑
六、依赖倒置原则
oo设计原则,要依赖抽象,不要依赖具体类。不仅仅是面向接口编程,不针对实现编程。不要让高层组件依赖底层组件。
  (1)变量不可以持有具体类的引用,不要用new
  (2)不要让类派生具体类
  (3)不要覆盖基类中已有的方法
七、最少知道原则(迪米特法则)
减少对象之间交互,只和你的密友谈话。
八、单一职责原则
一个类应该只有一个引起变化的原因,每个类应该保持单一责任。
内聚概念:衡量一个类或模块紧密达到单一的责任或目的。

设计建议

KISS(Keep It Simple Stupid)

越简单 出现问题的概率就越少,例如单个方法或者单个类控制代码行数

YAGNI

不用的功能没有必要添加,不要过度设计,例如不用的接口就不用实现

DIY

不要重复设计

避免过早优化

过早优化会导致代码复杂性

Law of Demeter

迪米特法则(Law of Demeter)又叫作最少知识原则
降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关
所以说写代码的时候不要乱写依赖关系。

23种设计模式

工厂模式(xxxFactory)

使用工厂模式其实就是为了减少代码里面出现new关键字的次数,同时可以集中管理对象的创建,同时隐蔽对象创建的细节。
打个比方如果项目代码里面有个类A被new了100多次,如果这个时候A类的构造方法需要加个参数,
那就意味着这100多个使用到类A的地方都需要相对应的跟着修改。
当然现在如果使用spring框架,很少会有自己new对象的场景,spring通过控制反转(ioc)和 依赖注入(di)
将类与类直接的依赖关系交给容器去管理,当需要哪个类直接注入进来就可以。

工厂模式可以抽象出来几个关键字抽象产品,具体产品,抽象工厂,具体工厂

(1)简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,父类是具体的。
(2)工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成。
(3)抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。它针对的是有多个产品的等级结构。
 而工厂方法模式针对的是一个产品的等级结构,在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。

简单工厂模式

public interface JDBC {
    void connection();
}

public class MysqJDBC implements  JDBC{
    @Override
    public void connection() {
        System.out.println("mysql connection");
    }
}

public class OraclJDBC  implements  JDBC{
    @Override
    public void connection() {
        System.out.println("OraclJDBC connection");
    }
}

public class JDBCFactory {
    //1
    public static  JDBC getJDBC(String type){
        if(type.equalsIgnoreCase("mysql"))return new MysqJDBC();
        if(type.equalsIgnoreCase("oracl"))return new OraclJDBC();
        return null;
    }
    //2
    public static  JDBC getMsqlylJDBC(){
         return new MysqJDBC();
    }
    //2
    public static  JDBC getOraclJDBC(){
         return new MysqJDBC();
    }

}

public class SimpleFactoryTest {
    public static void main(String[] args) {
        JDBCFactory.getJDBC("mysql").connection();
        JDBCFactory.getMsqlylJDBC().connection();
    }
}

2相比1的写法好处在于不会因为传入错误的字符串导致没能获取到正常的对象。

工厂方法模式

 你可以避免创建者和具体产品之间的紧密耦合。
 单一职责原则。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
 开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。
设计模式的规则是对扩展开放,对修改关闭。如果上面的例子这时候需要再增加一个sqlServer类型对象
就需要修改JDBCFactory类,例如增加下面的步骤3这就违法了我们的设计模式开放关闭原则

public class JDBCFactory {
        //1
        public static  JDBC getJDBC(String type){
            if(type.equalsIgnoreCase("mysql"))return new MysqJDBC();
            if(type.equalsIgnoreCase("oracl"))return new OraclJDBC();
            return null;
        }
        //2
        public static  JDBC getMsqlylJDBC(){
             return new MysqJDBC();
        }
        //2
        public static  JDBC getOraclJDBC(){
             return new MysqJDBC();
        }
        //3
        public static  JDBC getSqlServerJDBC(){
             return new SqlServerJDBC();
        }

    }
这时候就引入工厂方法模式,创建一个工厂接口,和多个工厂实现类,这个时候如果需要引入新对象,
只用创建新的工厂实现类就可以,避免了在原来的接口上修改。
工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。

public interface JDBCFactory {
    JDBC create();
}

public class MysqlFactory implements JDBCFactory{
    @Override
    public JDBC create() {
        return new MysqJDBC();
    }
}

public class SqlServerFactory implements JDBCFactory{
    @Override
    public JDBC create() {
        return new  SqlServerJDBC();
    }
}

public class Test {
    public static void main(String[] args) {
        JDBCFactory factoryOne=new MysqlFactory();
        factoryOne.create().connection();
        JDBCFactory factoryTwo=new SqlServerFactory();
        factoryTwo.create().connection();
    }
}

抽象工厂模式

当一个工厂需要生产多个产品的时候就需要用到抽象工厂模式。
打个比方,我们对每个数据源都需要加想对应的监控功能,那么一个工厂
就需创建对应的数据源对象,同时也要创建对应的监控类

 public class MysqlFactory implements JDBCFactory{
    @Override
    public JDBC create() {
        return new MysqJDBC();
    }
    //创建多个工厂
    @Override
    public XXX createMonitor() {
        return new XXX();
    }
 }

单例模式(xxxSingleton)

单例模式作用在于在当前系统内存里面,只有唯一一个该类的实例。
打个比方如果某个类的创建比较耗时,或者好资源,例如数据库连接池,线程池等等
使用单例模式创建连接池,这样系统里面就只有一份连接池数据

public class Singleton {
    /**
     * 私有化构造器
     */
    private Singleton(){};


    /**
     * 饿汉模式
     */
    private static Singleton singleton=new Singleton();
    public static synchronized Singleton getSingleton(){
        return  singleton;
    }

    /**
     * 懒汉模式
     */
    private static Singleton singleton2;
    public static synchronized  Singleton getSingleton2(){
        if(singleton2==null){
            singleton2=new Singleton();
        }
        return  singleton2;
    }

    /**
     * douleCheck
     */

    private static volatile Singleton singleton3;
    public static Singleton getSingleton3(){
        if(singleton3==null){
           synchronized (Singleton.class){
               if(singleton3==null){
                   //非原子操作,可能导致指令重新排序
                   singleton3=new Singleton();
               }
           }
        }
        return  singleton3;
    }

    /**
     * 匿名类
     */
    private static class SingletonHolder{
       private static final   Singleton singleton=new Singleton();
    }

    public static Singleton getSingleton4(){
        return  SingletonHolder.singleton;
    }

}

建造者模式(Builder)

将一系列的对象构建用builder来实现
工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象
下面的例子提供了两种build模式
@Data
public class People {
    private Car car;
    private Cat cat;
    private Dog dog;
    private int age;
    private String Name;
}

public class PeopleBuilder<T extends People> {
    private Car car;
    private Cat cat;
    private Dog dog;
    private int age;
    private String name;

    public PeopleBuilder buyCar() {
        this.car = new Car();
        return this;
    }


    public PeopleBuilder getTwoCat() {
        this.cat = new Cat();
        return this;
    }


    public PeopleBuilder getOneDog() {
        this.dog = new Dog();
        return this;
    }


    public PeopleBuilder setAge(int age) {
        this.age = age;
        return this;
    }


    public PeopleBuilder setName(String name) {
        this.name = name;
        return this;
    }

    public static PeopleBuilder<People> build() {
        return new PeopleBuilder();
    }

    public T create() {
        People people = new People();
        people.setAge(age);
        people.setCar(car);
        people.setCat(cat);
        people.setDog(dog);
        people.setName(name);
        return (T) people;
    }
}


public class PeopleRquest {

    public static class Builder {
        private Car car;
        private Cat cat;
        private Dog dog;
        private int age;
        private String name;

        public static Builder builder() {
            return new Builder();
        }

        public Builder buyCar() {
            this.car = new Car();
            return this;
        }


        public Builder getTwoCat() {
            this.cat = new Cat();
            return this;
        }


        public Builder getOneDog() {
            this.dog = new Dog();
            return this;
        }


        public Builder setAge(int age) {
            this.age = age;
            return this;
        }


        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public People build() {
            People people = new People();
            people.setAge(age);
            people.setCar(car);
            people.setCat(cat);
            people.setDog(dog);
            people.setName(name);
            return people;
        }
    }

}


public class Test {
    public static void main(String[] args) {
        PeopleBuilder.build().getOneDog().getTwoCat().buyCar().setAge(28).create();
        PeopleRquest.Builder.builder().getOneDog().getTwoCat().buyCar().setAge(28).build();
    }
}

原型模式(Prototype)

其实就是Java的浅拷贝和深拷贝
浅拷贝就是类的clone
深拷贝就是实现Cloneable接口,重写clone类
或者直接序列化

public class LowCopy implements Cloneable{
    private String name;
    private People people;

    public People getPeople() {
        return people;
    }

    public void setPeople(People people) {
        this.people = people;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    @Override
    protected LowCopy clone() throws CloneNotSupportedException {
        return (LowCopy)super.clone();
    }
}

public class People implements Serializable {

    private static final long serialVersionUID = -2929685135774849974L;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Prototype {
    public static void main(String[] args) throws Exception {
        People people=new People();
        people.setName("gao");
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bao);
        oos.writeObject(people);
        ByteArrayInputStream bais=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bais);
        People deepCopy= (People) ois.readObject();
        System.out.println(people==deepCopy);

        //浅拷贝不会拷贝对象里面的引用
        LowCopy lowCopy=new LowCopy();
        lowCopy.setName("gao");
        lowCopy.setPeople(people);
        LowCopy copy = lowCopy.clone();
        System.out.println(lowCopy==copy);
        System.out.println(lowCopy.getPeople()==copy.getPeople());
    }
}

适配器(Adapter)

系统需要使用现有的类,但此类已经不符合系统的需要
适配器模式是将某个类的接口转换成成用户所期待的接口,目的是消除由于接口不匹配所造成的类的兼容性问题
适配器模式有分成类的适配器模式,对象的适配器模式,接口的适配器模式
可以说Source的存在形式决定了适配器的名字。
类适配器就是继承Source类,对象适配器就是持有Source类,接口适配器就是实现Source接口。

类的适配器模式

例如下面的例子,我们是对Source类进行适配,我们需要继承Source类,同时实现ChargeTargetAable扩充
Source类的功能。
public class Source {
    public void charege(){
        System.out.println("直接充电");
    }
}

public interface  ChargeTargetAable  {
    void charege();
}

public class Adapter extends Source implements ChargeTargetAable{
    @Override
    public void charege() {
        System.out.println("装饰加转化器");
        super.charege();
    }
}

public class Test {
    public static void main(String[] args) {
        Source source=new Source();
        source.charege();
        ChargeTargetAable adapter=new Adapter();
        adapter.charege();
    }
}

对象的适配器模式

使用类的适配器必须要继承需要装饰的类,java是单继承的,如果适配器类需要继承其他类就得使用对象的适配器方式

public class Adapter implements ChargeTargetAable {
    private Source source;
    public Adapter(Source source) {
        this.source=source;
    }
    @Override
    public void charege() {
        System.out.println("装饰加转化器");
        source.charege();
    }
}

public class Test {
    public static void main(String[] args) {
        Source source=new Source();
        ChargeTargetAable adapter=new Adapter(source);
        adapter.charege();
    }
}

接口的适配器模式

有时候我们定义一个接口,接口中有很多抽象方法,我们实现改类时候,必须实现该类的所有方法,这时候就有点浪费
因为我们不一定使用所有方法,这时候就需要接口的适配器模式,利用一个抽象类实现该接口,然后我们写一个类
继承该抽象类,然后重写我们想要的方法就可以。

例如Apache commons-pool2类的 ObjectPool接口,BaseObjectPool抽象类继承了ObjectPool
abstract class BaseObjectPool<T> implements ObjectPool

public interface ChargeTargetAable {
    void charegeSH();
    void charege();
    void charegeHK();
    void charegeBJ();
}

public abstract class ChargeWrapper implements ChargeTargetAable {
    @Override
    public void charegeSH() {
    }

    @Override
    public void charege() {
        System.out.println("直接充电");
    }

    @Override
    public void charegeHK() {
    }

    @Override
    public void charegeBJ() {
    }
}


public class Adapter extends ChargeWrapper{
    @Override
    public void charege() {
        System.out.println("装饰加转化器");
        super.charege();
    }
}

public class Test {
    public static void main(String[] args) {
        Adapter adapter=new Adapter();
        adapter.charege();
    }
}

装饰模式(decorator)

装饰模式在某些场景和适配器模式类似,但是这两个是完全不同的概念,一个是扩展(静态扩展),一个是增强(动态扩展)。
装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
可以随意的选择需要装饰几个类,最里面是需要被装饰的类
装饰器模式是一种结构性模式,它作用是对对象已有功能进行增强,但是不改变原有对象结构。这避免了通过继承方式进行功能扩充导致的类体系臃肿。

public abstract class SimpleImage {
    SimpleImage simpleImage;
    abstract void render();
}

public class ImageReaderHelper extends SimpleImage {
    @Override
    void render() {
        System.out.println("开始处理图片");
    }
}

public class ImgeDarwReader extends SimpleImage {

    public ImgeDarwReader(SimpleImage ir) {
        simpleImage = ir;
    }

    @Override
    void render() {
        simpleImage.render();
        System.out.println("图片花线处理");
    }

}

public class ImgScanerReader extends SimpleImage {

    public ImgScanerReader(SimpleImage ir) {
        simpleImage = ir;
    }

    @Override
    void render() {
        simpleImage.render();
        System.out.println("图片扫描处理");
    }

}

public class MainTest {
    public static void main(String[] args) throws Exception {
        ImgScanerReader isr = new ImgScanerReader(new ImgeDarwReader(new ImageReaderHelper()));
        isr.render();
    }
}

代理模式(proxy)

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
打个比方,在我们使用一些开源框架client端时候,都会在原有client端包装一层代理类,
防止因为client因为api升级导致方法不兼容,还有一种就是spring aop java的动态代理

public interface Image {
    void display();
}

public class RealImage implements Image {
    private String fileName;
    public RealImage(String fileName){
        this.fileName = fileName;
    }
    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }
}

public class ProxyImag implements Image {
    @Override
    public void display() {
        System.out.println("代理啊 ");
        new RealImage("real").display();
    }
}

public class Test {
    public static void main(String[] args) {
        Image image=new ProxyImag();
        image.display();
    }
}

区别

1、适配器模式的区别:适配器模式主要改变所考虑对象的接口(创建新的接口),而代理模式不能改变所代理类的接口。
2、装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制

适配器可以对已有对象的接口进行修改,
装饰模式则能在不改变对象接口的前提下强化对象功能。 此外, 装饰还支持递归组合, 适配器则无法实现

外观模式(Facade)

外观模式就是封装交互,简化调用,但是不符合开闭原则,如果要改东西很麻烦,
因为每次改都是改facade类里面的逻辑。
例如去医院体检,我们可能需要去眼科,外科,内科,口腔,抽血等地方排队体检,可能抽血的需要等10分钟,但是眼科只需要等1分钟,或者
外科在1楼,眼科在三楼,这个时候如果有个接待员(门面),他能协调我们当前项目体检完后,下一个项目去哪个科室体检最快,是不是非常方便
,我们不用关系排队时间和地点,他们会直接引领我们过去。
例如JAVA 的三层开发模式MVC,

桥接模式(Bridge)

将抽象部分与实现部分分离,使它们都可以独立的变化。
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
例如颜色(红、黄、蓝色)和形状(正方形、长方形、原型),颜色和形状组合那么会有3*3种情况,如果只是用java继承去实现
那么可能会有9个类,这时候可以利用桥接模式,将继承转换成关联,这样就降低类之间耦合度,同时减少系统中类的数量。
又例如mysql的数据连接DriverManager、 mysqlDriver 和 oracleDriver 都实现java.sql.Driver接口

public interface Shape {
    String getShape();
}

public class Square implements Shape{
    @Override
    public String getShape() {
        return "正方形";
    }
}

public class Circle implements Shape{
    @Override
    public String getShape() {
        return "圆形";
    }
}

public abstract class ColorBridge {
     protected Shape shape;
     public abstract void diplayColor();
}

public class BlueColor extends ColorBridge {
    public BlueColor(Shape shape) {
        this.shape=shape;
    }
    @Override
    public void diplayColor() {
        System.out.println("blue:" + shape.getShape());
    }
}

public class ReadColor extends ColorBridge {
    public ReadColor(Shape shape) {
        this.shape = shape;
    }

    @Override
    public void diplayColor() {
        System.out.println("red:" + shape.getShape());
    }
}

public class Test {
    public static void main(String[] args) {
        Shape cycle=new Circle();
        Shape square=new Square();

        ColorBridge red=new ReadColor(cycle);
        ColorBridge blue=new BlueColor(cycle);
        red.diplayColor();
        blue.diplayColor();

        //新增正方形 不需要新增类
        ColorBridge red2=new ReadColor(square);
        ColorBridge blue2=new BlueColor(square);
        red2.diplayColor();
        blue2.diplayColor();
    }
}

桥接模式通常会于开发前期进行设计, 使你能够将程序的各个部分独立开来以便开发。
另一方面, 适配器模式通常在已有程序中使用, 让相互不兼容的类能很好地合作。

组合模式

是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
例如我们常见的树状数据结构数据

享元模式

主要用于减少创建对象的数量,以减少内存占用和提高性能。
例如各种线程池,或者一些对象可以被复用就直接放在Map里面

策略模式(strategy)

https://www.runoob.com/design-pattern/strategy-pattern.html
策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户
主要解决在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
(可以用表驱动法,如果用spring 可以先定义好 (key,springbean))
需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,
设计一个抽象类(可有可无,属于辅助类),提供辅助函数,然后依赖该接口
其实就是面向接口开发。

public interface Strategy {
   public int doOperation(int num1, int num2);
}


public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubstract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class Context {
   private Strategy strategy;

   public Context(Strategy strategy){
      this.strategy = strategy;
   }

   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}


public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationSubstract());
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

      context = new Context(new OperationMultiply());
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}

和适配器有点类似,都是引入依赖类。

模板模式(template)

一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
其实就是继承、重写。

观察者模式(Observer)

对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
 例如spring的ApplicationListener与ApplicationEvent 可以实现观察者模式,同时解耦代码

迭代子模式(iterator)

提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示
例如集合的迭代器

责任链模式(chain)

有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求
例如spring的 的拦截器,javaWeb的Filter,dubbo的filter
下面的例子是内置责任链模式,将所有引用存在ApplicationFilterChain里面,
public interface Filter {
    void doFilter(int age,FilterChain filterChain);
}
public class DefaultFilter implements Filter {
    @Override
    public void doFilter(int age, FilterChain filterChain) {
        log.info("DefaultFilter=>study");
        if(age>25) {
            filterChain.chain(age);
        }
    }
}
public class BuyCarFilter implements Filter{
    @Override
    public void doFilter(int age, FilterChain filterChain) {
        log.info("BuyCarFilter");
        if(age>=27) {
            filterChain.chain(age);
        }
    }
}
public class MarryFilter implements Filter{
    @Override
    public void doFilter(int age, FilterChain filterChain) {
        log.info("MarryFilter");
        if(age>=30) {
            filterChain.chain(age);
        }
    }
}
public class BabyFilter implements Filter{
    @Override
    public void doFilter(int age, FilterChain filterChain) {
        log.info("BabyFilter");
        filterChain.chain(age);
    }
}

public interface FilterChain {
    void chain(int age);
}
//FilterChain 里面维护了所有 Filter执行顺序
public class ApplicationFilterChain implements FilterChain {
    private  List<Filter> filterList = new ArrayList<>();

    public ApplicationFilterChain(){
       filterList.add(new DefaultFilter());
      filterList.add(new BuyCarFilter());
       filterList.add(new MarryFilter());
        filterList.add(new BabyFilter());
    }
    @Override
    public void chain(int age) {
        if (CollectionUtils.isNotEmpty(filterList)) {
            Filter filter = getNextFilter();
            filter.doFilter(age, this);
        }else{
            log.info("exit");
        }
    }

    private Filter getNextFilter() {
        Filter filter = filterList.get(0);
        filterList.remove(0);
        return filter;
    }
}

public class Test {
    public static void main(String[] args) {
        FilterChain filterChain = new ApplicationFilterChain();
        //filterChain.chain(20);
        filterChain.chain(27);
        //filterChain.chain(31);
    }
}

外置责任链模式:关系放在最外面

public abstract class AbstractFilter {
    private AbstractFilter nextFilter;
    protected int needAge;

    public void setNextFilter(AbstractFilter nextFilter) {
        this.nextFilter = nextFilter;
    }

    public void excute(int age) {
        doFilter();
        if (age > needAge) {
            nextFilter.excute(age);
        }
    }
    public abstract void doFilter();
}

public class DefaultFilter extends AbstractFilter{

    public DefaultFilter(int needAge) {
        super.needAge=needAge;
    }

    @Override
    public void doFilter() {
        log.info("DefaultFilter");
    }
}

public class BuyCarFilter extends AbstractFilter{

    public BuyCarFilter(int needAge) {
        super.needAge=needAge;
    }
    @Override
    public void doFilter() {
        log.info("BuyCarFilter");
    }
}

@Slf4j
public class MarryFilter extends AbstractFilter {
    public MarryFilter(int needAge) {
        super.needAge = needAge;
    }

    @Override
    public void doFilter() {
        log.info("MarryFilter");
    }
}

public class MarryFilter extends AbstractFilter {
    public MarryFilter(int needAge) {
        super.needAge = needAge;
    }

    @Override
    public void doFilter() {
        log.info("MarryFilter");
    }
}


public class Test {
    public static void main(String[] args) {
        AbstractFilter defaultFilter=new DefaultFilter(20);
        AbstractFilter buyCarFilter=new BuyCarFilter(25);
        AbstractFilter marryFilter=new MarryFilter(27);
        AbstractFilter babyFilter=new BabyFilter(30);
        defaultFilter.setNextFilter(buyCarFilter);
        buyCarFilter.setNextFilter(marryFilter);
        marryFilter.setNextFilter(babyFilter);

        defaultFilter.excute(26);
        //defaultFilter.excute(30);
    }
}

访问者模式id

责任链模式与装饰者模式

责任链通常是有预定义的链条的;而装饰者更多的是根据实际情况自定义装饰、处理顺序的。
个人理解装饰者起到对是增强的概念。

开源框架里面的用到的模式

spring

工厂方法模式

BeanFactory模式创建bean

单例模式

如果bean的scope为singleton,那么都会放到singletonObjects的map里面
Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>

原型设计模

如果bean的作用域是prototype ,那么每次创建都是一个新类

策略模式

Spring中bean实例化策略,接口InstantiationStrategy是实例化策略接口类,
它定义了三个实例化接口,然后SimpleInstantiationStrategy实现了该策略,它主要做一些简单的根据构造函数实例号bean的工作,
然后CglibSubclassingInstantiationStrategy又继承了SimpleInstantiationStrategy新增了方法注入方式根据cglib生成代理类实例化方法
另外AopProxy也是一个策略接口类,具体实现的策略为JdkDynamicAopProxy,CglibAopProxy,ObjenesisCglibAopProxy

适配器模式

spring的MethodInterceptor的适配器
AfterReturningAdvice和MethodBeforeAdvice没有实现MethodInterceptor接口。而Spring
Aop的方法拦截器却必须是实现了MethodInterceptor的,所以Spring提供了对应的适配器来适配这个问题
分别是MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter和ThrowsAdviceAdapter
DefaultAdvisorAdapterRegistry类代码
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);

    //从advistor中获取advice
    Advice advice = advisor.getAdvice();

    //如果实现了MethodInterceptor则直接加入,比如AspectJAroundAdvice,AspectJAfterAdvice
    if (advice instanceof MethodInterceptor) {
        interceptors.add((MethodInterceptor) advice);
    }

    //否者看是否有当前advice的适配器,首先检验是否支持,支持则返回对应的适配器
    for (AdvisorAdapter adapter : this.adapters) {
        if (adapter.supportsAdvice(advice)) {
            //适配器获取interceptors
            interceptors.add(adapter.getInterceptor(advisor));
        }
    }
    if (interceptors.isEmpty()) {
        throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}

//代理类
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }

}
例如:MethodBeforeAdviceInterceptor继承了MethodInterceptor作为了一个适配器内部委托请求给MethodBeforeAdvice

模板模式

例如JdbcTemplate,定义了一系列的模板方法,我们不用关心数据源的获取和关闭,直接调用即可。

public <T> T execute(ConnectionCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");

        Connection con = DataSourceUtils.getConnection(getDataSource());
        try {
            Connection conToUse = con;
            if (this.nativeJdbcExtractor != null) {
                // Extract native JDBC Connection, castable to OracleConnection or the like.
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }
            else {
                // Create close-suppressing Connection proxy, also preparing returned Statements.
                conToUse = createConnectionProxy(con);
            }
            return action.doInConnection(conToUse);
        }
        catch (SQLException ex) {
            // Release Connection early, to avoid potential connection pool deadlock
            // in the case when the exception translator hasn't been initialized yet.
            DataSourceUtils.releaseConnection(con, getDataSource());
            con = null;
            throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
        }
        finally {
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }

观察者模式

spring里面的ApplicationListener与ApplicationEvent
AbstractApplicationContext属于发布者,可以添加不同的listener,同时发布不同event类型的消息,
listener属于订阅者,event属于订阅者的类型,订阅者只监听属于自己类型的消息
我们可以自定义自己的envent类型只要继承ApplicationEvent就可以
spring自定了好几个event 这些event都继承了ApplicationContextEvent,而
ApplicationContextEvent都继承了ApplicationEvent
1、ContextClosedEvent  对应 ContextCloserListener
2、ContextRefreshedEvent  对应  ContextRefreshListener
    IOC刷新完成(也就是bean解析完成,创建完毕并且autowired完成)后的事件 这个经常用
3、ContextStartedEvent
4、ContextStoppedEvent

参考

设计模式
常用开源框架中设计模式使用分析