深入理解Spring(七)、Spring常用设计模式

>>强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

前言

深入理解Spring源码分为7小节,本小节为Spring源码第7小节,各个小节目录如下。

  1. 扫描过程
  2. bean创建过程
  3. 容器扩展
  4. AOP源码分析
  5. 事务源码分析
  6. Spring JDBC源码分析

7.  Spring常用设计模式

优秀的框架多多少少都会用到一些设计模式,Spring也不例外,但是这些模式可能你看多少遍都不明白,为什么这样写,这不是多此一举吗,设计模式需要写大量代码,才能从中间悟出来他的真谛。

下面来介绍Spring常用的几种。

工厂模式

工厂模式用来创建对象,使用频率比较高,下面举例。

现在有很多不同品牌的电脑,如ThinkPad、Mac,他们我们把他们的厂商抽象成工厂,每个工厂可以生产不同电脑,定义如下。

public abstract class AbstractComputerFactory {
    public abstract <T extends AbstractComputer> AbstractComputer createComputer(Class<T> computerClass);
}

public abstract class AbstractComputer {
  public   abstract void start();
    public  abstract void shutdown();
}

工厂实现类。

public class ComputerFactory extends AbstractComputerFactory {
    @Override
    public <T extends AbstractComputer> AbstractComputer createComputer(Class<T> computerClass) {
        try {
            return computerClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}
public class Main {
   static class ThinkPadComputer extends AbstractComputer{
        @Override
        public void start() {
        }
        @Override
        public void shutdown() {
        }
    }
    static class MacComputer extends AbstractComputer{
        @Override
        public void start() {
            System.out.println("mac start");
        }
        @Override
        public void shutdown() {
            System.out.println("mac shutdown");
        }
    }
    public static void main(String[] args) {
        AbstractComputer computer = new ComputerFactory().createComputer(MacComputer.class);
        computer.start();
    }
}

上面我们称为简单工厂,还可以上升到另一个层面,叫抽象工厂。联想现实中的工厂都是具体的,也就是每个工厂都会生产某一中具体的产品,那么抽象工厂意味着生产出来的产品不是确定的。

抽象工厂的定义是为一组相关的对象提供一个接口。

还拿上面制作电脑的来说,每种工厂创建的产品内部零件可能都不一样,比如ThinkPad X1隐士使用的CPU是Intel Core i9,屏幕尺寸是16,而ThinkPad X13的CPU是Intel Core i5,屏幕尺寸是13,我们为这个进行工厂抽象。

public abstract class ICpu {
    public abstract void createCpu();
}

public abstract class IScreen {
    public abstract void createScreen();
}

不同的产品实现类。

public class Screen13 extends IScreen {
    @Override
    public void createScreen() {
        System.out.println("屏幕13");
    }
}
public class Screen16 extends IScreen {
    @Override
    public void createScreen() {
        System.out.println("屏幕16");
    }
}

public class IntelI5 extends ICpu {
    @Override
    public void createCpu() {
        System.out.println("Intel i5");
    }
}

public class IntelI9  extends ICpu {
    @Override
    public void createCpu() {
        System.out.println("Intel i9");
    }
}

抽象工厂

public abstract class ThinkPadFactory {
    public abstract ICpu createCpu();
    public abstract IScreen createScreen();
}

ThinkPad x1的实现。

public class ThinkPadX1Factory extends ThinkPadFactory {
    @Override
    public ICpu createCpu() {
        return new IntelI9();
    }
    @Override
    public IScreen createScreen() {
        return new Screen16();
    }
}

ThinkPad x13的实现。

public class ThinkPadX13Factory extends ThinkPadFactory {
    @Override
    public ICpu createCpu() {
        return new IntelI5();
    }
    @Override
    public IScreen createScreen() {
        return new Screen13();
    }
}
public class Main {
    public static void main(String[] args) {
        ThinkPadX1Factory thinkPadX1Factory = new ThinkPadX1Factory();
        thinkPadX1Factory.createCpu().createCpu();
        ThinkPadX13Factory thinkPadX13Factory = new ThinkPadX13Factory();
        thinkPadX13Factory.createCpu().createCpu();
    }
}

Spring中很多Factory,核心BeanFactory就是一个。

原型模式

原型模式的核心是一个clone方法,可以通过这个方法进行对象拷贝,拷贝的对象和原来对象是不同的,但是里面字段值是一样的,网上可能有这样一个面试提,new和clone那个快?这其实不一定谁快谁慢,还是看场合,比如在构造方法执行了一些耗时的事情,那么clone会比较快,因为clone不会重新执行构造方法。

如下,被clone的对象必须实现Cloneable。

Email email = new Email("1111@qq.com""数据i");
Email clone = email.clone();
clone.setContent("数据2");
System.out.println(email.equals(clone));

public class Email implements Cloneable {
   private String sender;
   private String content;
   @Override
   public Email clone() {
       try {
           Email clone = (Email) super.clone();
           return clone;
       } catch (CloneNotSupportedException e) {
           e.printStackTrace();
       }
       return null;
   }
   public Email(String sender, String content) {
       this.sender = sender;
       this.content = content;
   }

   public String getSender() {
       return sender;
   }
   public void setSender(String sender) {
       this.sender = sender;
   }

   public String getContent() {
       return content;
   }
   public void setContent(String content) {
       this.content = content;
   }
}

代理模式

代理是个很常用的模式,举个例子,对象A是老大,你想要和老大沟通,但必须和老大的跟班先请示,跟班可能会拒绝掉一些无用信息。

public abstract class Subject {
   public abstract void visit();
}

public class RealSubject  extends Subject{
   @Override
   public void visit() {
       System.out.println("原方法");
   }
}

public class ProxySubject  extends Subject{
   private RealSubject realSubject;
   public ProxySubject(RealSubject realSubject) {
       this.realSubject = realSubject;
   }
   @Override
   public void visit() {
       if (LocalDateTime.now().getHour()>23){
           return;
       }
       realSubject.visit();
   }
}


ProxySubject proxySubject = new ProxySubject(new RealSubject());
proxySubject.visit();

上面所示的静态代理,还有动态代理,比如使用Proxy、CGLIB这种方法,Spring的AOP就是使用动态代理。

策略模式

每个问题都有不同的解决方法,或者每个时机都有不同的方法,策略模式就是解决这个问题,比如女朋友特别爱打我,可气的还是她会分不同时间打,早上一把打2次,中午打3次,晚上打的就更多了,10次。我们把这个打抽象为接口。

public interface Hit {
   public void start();
}

女朋友

public class Girl {
    private Hit hit;
    public void setHit(Hit hit) {
        this.hit = hit;
    }
    public void start() {
        hit.start();
    }
}
public class Main {
    static class MorningHit implements Hit {
        @Override
        public void start() {
            for (int i = 0; i < 2; i++) {
                System.out.println("打我");
            }
        }
    }
    static class NoonHit implements Hit {
        @Override
        public void start() {
            for (int i = 0; i < 3; i++) {
                System.out.println("打我");
            }
        }
    }
    static class NightHit implements Hit {
        @Override
        public void start() {
            for (int i = 0; i < 10; i++) {
                System.out.println("打我");
            }
        }
    }

    public static void main(String[] args) {
        Girl girl = new Girl();

        girl.setHit(new NightHit());
        girl.start();

    }
}

模板模式

每个问题可能都有一套固定的模板解决,同样是女朋友打我,总会先捋起袖子、然后上手,但是在超级生气的时候,不会上手,而是上脚。

public abstract class Hit {
    public void 捋起袖子() {
        System.out.println("捋起袖子");
    }
    public void 开打() {
        System.out.println("上手");
    }
    public void begin() {
        捋起袖子();
        开打();
    }
}
public class Girl {
    private Hit hit;
    public void setHit(Hit hit) {
        this.hit = hit;
    }
    public void begin() {
        hit.begin();
    }
}
public class Main {
    static class BaseHit extends Hit{}
    static class SeriousHit extends Hit{
        @Override
        public void 开打() {
            System.out.println("上脚");
        }
    }
    public static void main(String[] args) {
        Girl girl = new Girl();
        girl.setHit(new BaseHit());
        girl.begin();
        girl.setHit(new SeriousHit());
        girl.begin();
    }
}

输出如下。

捋起袖子
上手
捋起袖子
上脚

- END -


原文始发于微信公众号(十四个字节):深入理解Spring(七)、Spring常用设计模式