Spring中的设计模式
spring用到的设计模式主要有哪些:
1.工厂模式,这个很明显,在各种BeanFactory以及ApplicationContext创建Bean中都用到了;
2.模版模式,Spring 中 jdbcTemplate、hibernateTemplate 等以 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(); } } }
浙公网安备 33010602011771号