无风无影

   ::  :: 新随笔  ::  ::  :: 管理

Spring中的设计模式

  spring用到的设计模式主要有哪些:

  1.工厂模式,这个很明显,在各种BeanFactory以及ApplicationContext创建Bean中都用到了;

  2.模版模式Spring 中 jdbcTemplatehibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  3.代理模式,在Aop实现中用到了JDK的动态代理;

  4.策略模式,第一个地方,加载资源文件的方式,使用了不同的方法,比如:ClassPathResourece,FileSystemResource,ServletContextResource,UrlResource但他们都有共同的借口Resource;第二个地方就是在Aop的实现中,采用了两种不同的方式,JDK动态代理和CGLIB代理;

  5.单例模式,这个比如在创建bean的时候, Spring 中的 Bean 默认都是单例的

   6.观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。

   7.适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller

一、工厂模式

  定义:工厂模式可将Java对象的调用者从被调用者的实现逻辑中分离出来,调用者只需关心被调用者必须满足的规则(接口),而不必关心实例的具体实现过程。工厂模式由抽象产品(接口)、具体产品(实现类)、生产者(工厂类)三种角色组成。优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

 

  Spring实现举例

  Spring中在各种BeanFactory以及ApplicationContext创建中都用到了典型的工厂方法模式,BeanFactory的设计原理如下图所示。 
Spring Bean的体系结构比较复杂,顶级接口是BeanFactory;BeanFactory共有三个子接口:ListableBeanFactory、HierarchicalBeanFactory和AutowireCapableBeanFactory,这三个子接口集成了顶级接口并对BeanFactory的功能进行了增强,称为二级接口;ConfigurableBeanFactory对二级接口HierarchicalBeanFactory进行了再次增强,它还继承了另一个外来的接口SingletonBeanRegistry,可以被称为三级接口;ConfigurableListableBeanFactory是一个更强大的接口,继承了上述的所有接口,称为四级接口。其余的为抽象类,实现了Spring Bean四级接口所定义的所有功能。

                                  

  

public interface Operation {
    public double getResult(double numberA,double numberB) throws Exception;
 
}

public class Add implements Operation{
    // 加法计算
    public double getResult(double numberA, double numberB) {
 
        return numberA + numberB;
    }
}
 
public class Sub implements Operation{
    // 减法计算
    public double getResult(double numberA, double numberB) {
        return numberA-numberB;
 }


public interface Factory {
 
    public Operation createOperation() ;

 }


// 加法类工厂
public class AddFactory implements Factory{
 
    public Operation createOperation() {
        System.out.println("加法运算");
        return new Add();
    }
}
 
// 减法类工厂
public class SubFactory implements Factory{
 
    public Operation createOperation() {
        System.out.println("减法运算");
        return new Sub();
 }


    public static void main(String[] args) throws Exception {
 
        // 使用反射机制实例化工厂对象,因为字符串是可以通过变量改变的
        Factory addFactory = (Factory) Class.forName("org.zero01.factory.AddFactory").newInstance();
        Factory subFactory=(Factory) Class.forName("org.zero01.factory.SubFactory").newInstance();
 
        // 通过工厂对象创建相应的实例对象
        Operation add = addFactory.createOperation();
        Operation sub = subFactory.createOperation();
 
        System.out.println(add.getResult(1, 1));
        System.out.println(sub.getResult(1, 1));

}

  模板模式

   在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

   优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

public abstract class Game {
   abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();
 
   //模板
   public final void play(){
 
      //初始化游戏
      initialize();
 
      //开始游戏
      startPlay();
 
      //结束游戏
      endPlay();
   }
}

public class Cricket extends Game {
 
   @Override
   void endPlay() {
      System.out.println("Cricket Game Finished!");
   }
 
   @Override
   void initialize() {
      System.out.println("Cricket Game Initialized! Start playing.");
   }
 
   @Override
   void startPlay() {
      System.out.println("Cricket Game Started. Enjoy the game!");
   }
}

public class Football extends Game {
 
   @Override
   void endPlay() {
      System.out.println("Football Game Finished!");
   }
 
   @Override
   void initialize() {
      System.out.println("Football Game Initialized! Start playing.");
   }
 
   @Override
   void startPlay() {
      System.out.println("Football Game Started. Enjoy the game!");
   }
}

 public static void main(String[] args) {
 
      Game game = new Cricket();
      game.play();
      System.out.println();
      game = new Football();
      game.play();      
   }

  代理模式(Proxy pattern)

     代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式由抽象角色、代理角色和真实角色三种角色组成优点: 1、职责清晰。 2、高扩展性。 3、智能化。缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂

  Spring实现举例

  Spring的Proxy模式主要在Aop的实现中有体现,比如JdkDynamicAopProxy和Cglib2AopProxy,用到了JDK的动态代理模式。Spring中使用代理模式的结构如图3所示。$Proxy是创建的代理对象,Subject是抽象主题,代理对象是通过InvocationHandler来持有对目标对象的引用。除了实现被代理对象的接口外,还会有org.springframework.aop.SpringProxy和org.springframework.aop.framework.Advised两个接口。

                                                                                          

public interface Image {
   void display();
}

public class RealImage implements Image {
   private String fileName;
   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }

   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }
   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}

public class ProxyImage implements Image{
   private RealImage realImage;
   private String fileName;
 
   public ProxyImage(String fileName){
      this.fileName = fileName;
   }
 
   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

 public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");
      // 图像将从磁盘加载
      image.display(); 
      System.out.println("");
      // 图像不需要从磁盘加载
      image.display();  
   }

  策略模式(Strategy pattern)

     策略模式定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,使得算法可独立于使用它的客户而变化。策略模式由抽象策略角色、具体策略角色和环境角色三种角色组成。优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。 缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。

 

  Spring中策略模式的应用

  Spring中在实例化对象的时候用到Strategy模式,结构如图所示。Spring中抽象策略实现的核心是AopProxy接口;Cglib2AopProxy和JdkDynamicAopProxy集成了核心接口,分别代表两种策略的实现方式;ProxyFactoryBean代表Spring中的Context角色,它根据条件选择使用Jdk代理方式或者是CGLIB方式;而另外三个类主要是来负责创建具体策略对象;ProxyFactoryBean是通过依赖的方法来关联具体策略对象的,它是通过调用策略对象的getProxy(ClassLoader classLoader)方法来完成操作。

                                                              

    示例代码:下面的例子为加减乘除,不同计算方式的实现

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(){
      
   }
   public SetStrategy(Strategy strategy){
      this.strategy = strategy;
   }
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}

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

}

 

 

 

 

   观察者模式:

   

Subject.java

public class Subject { private List<Observer> observers = new ArrayList<Observer>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for (Observer observer : observers) { observer.update(); } } }
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}

public class OctalObserver extends Observer{
 
   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}
public static void main(String[] args) {
      Subject subject = new Subject();
 
      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);
 
      System.out.println("First state change: 15");   
      subject.setState(15);
      System.out.println("Second state change: 10");  
      subject.setState(10);
   }

 

   缺点:

  • 客户端必须知道所有的【观察者】,并且进行【增加观察者】和【删除观察者】的操作。

  • 如果有很多【观察者】,那么所有的【观察者】收到通知,可能需要花费很久时间。

  spring中的应用可参考:https://www.jianshu.com/p/5e72c6b76c72

 

  适配器模式:  

  适配器有两种:类适配器和对象适配器,类适配器通过继承类和实现接口,但一般不常用,而是用对象适配器的组合模式。 缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握;对于类的话,由于 JAVA 至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类;

  举例如下:接口MP4,MP4实现类,假设现在有个MP3接口,可以共用MP4的音乐播放,两种方式分别如下:

类适配器代码如下:

public interface MP4{
    void play();
}
public class MP4Impl implement MP4{
    public void play(){
            // todo
    }
}

public interface IMP4Adapter{
      void action();
}
public class MP4Adapter extends MP4Impl implement IMP4Adapter{
  public void action(){ play(); } 
}
对象适配器代码:
public class MP4Adapter implement IMP4Adapter{ public MP4 mp4; public PlayerAdapter (MP4 mp4){ this.mp4 = mp4; } public void action(){ if(mp4!= null){ mp4.play(); } } }

 

posted on 2020-01-04 11:10  NWNS-无风无影  阅读(258)  评论(0)    收藏  举报