Spring中常见的设计模式
一、代理模式
1.1 生活中的代理模式
1.1.1 特点
1、执行者、被代理人
2、对被代理人来说,这件事是一定要做的,但自己又不想做或者没时间做,找代理。
3、代理人需要获取被代理人的个人资料。
1.1.2 举例
- 租房中介:中介和你
- 火车票黄牛:黄牛和你
- 媒人:媒婆和你
1.2 程序中的代理模式
1.2.1 特点
1、事情必须做,而自己没有时间做或者不想做。
2、前提条件:持有被代理对象的引用。
1.2.2 分类
- 静态代理
- 动态代理:字节码重组,可以在每个方法执行前/后加一些代码。
1.2.3 实现方式
- JDK动态代理
- CGLib动态代理,cglib.jar(全称 Code Generation Library代码生成库)
- asm.jar(全称assembly,装配)
1.3 Spring中动态代理AOP应用
@Transactional
事务注解
1、开启一个事务(open)
2、事务的执行是由我们自己的代码完成
3、监听是否有异常,可能需要根据异常的类型类决定这个事务是否需要回滚还是继续提交(@Transactional(rollbackOn = Exception.class)
) (commit/roback)
4、关闭事务(close)
二、工厂模式
2.1 特点
隐藏复杂的逻辑处理过程,只关心执行结果(结果论)
2.2 阐述
生产者和消费者要区分开来,工厂模式是生产者端将产品生产过期封装起来,消费端不关心产品的生产过程和细节。
以买早餐:面包、牛奶(产品)为例,对消费者来说,消费者只关心产品保质期有没有过期?产品使用效果怎么样?(好不好吃)产品价格是否便宜?消费者并不关心面包、牛奶的生产工艺,生产过程的细节。
2.3 分类
- 简单工厂
- 工厂方法
- 抽象工厂
2.4 代码示例
2.4.1 简单工厂模式
public class SimpleFatory {
public Car getCar(String carName){
if("BMW".equals(carName)){
return new Bmv();
}else if("Benz".equals(carName)){
return new Benz();
}else if("Audi".equals(carName)){
return new Audi();
}else{
System.out.println("这个产品生产不了");
return null;
}
}
}
2.4.2 工厂方法模式
public interface CarFactory {
//生产符合汽车上路标准的汽车
Car getCar();
}
public class AudiFactory implements CarFactory {
@Override
public Car getCar() {
System.out.println("奥迪汽车");
return new Audi();
}
}
public class BenzFatory implements CarFactory {
@Override
public Car getCar() {
System.out.println("奔驰汽车");
return new Benz();
}
}
public class CarFactoryTest {
public static void main(String[] args) {
/**
* 工厂方法模式
* 各个产品的生产商,都拥有各自的工厂
* 需要用户(消费者)关心这个产品的生产商
* 增加了代码使用的复杂度
* 需要使用抽象工厂模式升级
*/
CarFactory carFactory = new AudiFactory();
System.out.println(carFactory.getCar());
carFactory = new BenzFatory();
System.out.println(carFactory.getCar());
}
}
2.4.3 抽象工厂模式
public abstract class AbstractCarFactory {
//生产符合汽车上路标准的汽车
protected abstract Car getCar();
/**
* 抽象工厂模式 : 简单工厂+工厂方法
* @param carName
* @return
*/
public Car getCar(String carName){
if("Benz".equals(carName)){
//产品通过工厂拿,屏蔽了产品生产的细节,简单工厂需要自己生产产品
return new BenzFactory().getCar();
}else if("Audi".equals(carName)){
return new AudiFactory().getCar();
}else{
System.out.println("这个产品生产不了");
return null;
}
}
}
public class AudiFactory extends AbstractCarFactory {
@Override
public Car getCar() {
System.out.println("奥迪汽车");
return new Audi();
}
}
public class BenzFactory extends AbstractCarFactory {
@Override
public Car getCar() {
System.out.println("奔驰汽车");
return new Benz();
}
}
public class DefaultCarFactory extends AbstractCarFactory{
@Override
public Car getCar() {
return new AudiFactory().getCar();
}
}
public class AbstractCarFactoryTest {
public static void main(String[] args) {
/**
* 抽象工厂模式 : 简单工厂+工厂方法
*/
DefaultCarFactory carFactory = new DefaultCarFactory();
//默认:奥迪车
System.out.println(carFactory.getCar());
//奔驰车
System.out.println(carFactory.getCar("Benz"));
//奥迪车
System.out.println(carFactory.getCar("Audi"));
}
}
2.5 Spring工厂模式应用
Spring中有BeanFactory类来生产各种Bean,通过getBean()
方法获得Bean
- 单例的Bean
- 被代理过的Bean
- 最原始的Bean,原型Bean
- List类型的Bean
- 作用域不同的Bean
三、单例模式
保证从系统启动到系统停止,全过程只会产生一个实例
四、委派模式
4.1 特点
1、类似于中介的功能(委托机制)
2、只有被委托人的引用
3、干活是我的(受托人),功劳是你的(委托人)
4.2 注意
需要和代理模式区分开来,委派模式不关心过程,只关心结果。
4.3 代码示例
public interface IExector {
/**
* 执行任务:
* 在公司中,普通员工执行任务
* 要求在一周内完成
*/
void doing();
}
public class ExectorA implements IExector {
@Override
public void doing() {
System.out.println("员工A执行任务");
}
}
public class ExectorB implements IExector {
@Override
public void doing() {
System.out.println("员工B执行任务");
}
}
public class Dispatcher implements IExector {
//具体执行者
private IExector exector;
public Dispatcher(IExector exector){
this.exector = exector;
}
/**
* 项目经理虽然也有执行方法,但他的工作职责是不一样的,主要是分配任务
*/
@Override
public void doing() {
//项目经理自己不做事,委派他人做事
exector.doing();
}
}
public class DispatcherTest {
public static void main(String[] args) {
Dispatcher dispatcher = new Dispatcher(new ExectorA());
//看上去是我们项目经理在干活,但实际干活的人是普通员工
//这就是典型的:干活是我的,功劳是你的
dispatcher.doing();
//打印:员工A执行任务
}
}
五、策略模式
5.1 阐述
过程不同,但结果一样
5.2 代码示例
public class Test {
public static void main(String[] args) {
List<Long> numbers = new ArrayList();
//策略模式,排序功能
Collections.sort(numbers, new Comparator<Long>() {
//返回值是固定的:-1,0,1
@Override
public int compare(Long o1, Long o2) {
//中间比较逻辑可能不一样
return 0;
}
});
}
}
六、原型模式
6.1 阐述
1、过程相同,但结果不一样。
2、数据内容完全一样,但实例不同。
七、模板模式
7.1 阐述
执行流程一样,但中间有些步骤不同。
7.2 代码示例
//冲饮料
public abstract class Bevegrage {
//定义成final,不让子类重写
public final void create() {
//1、把水烧开
boilWater();
//2、把杯子准备好,原材料放到杯中
pourInCup();
//3、用水冲泡
brew();
//4、添加辅料
addCoundimen();
}
protected abstract void pourInCup();
protected abstract void addCoundimen();
protected void boilWater() {
System.out.println("烧开水,烧到100度可以起锅了");
}
protected void brew() {
System.out.println("将开水倒入杯中进行冲泡");
}
}
//冲咖啡
public class Coffee extends Bevegrage{
//原材料放到杯中
@Override
protected void pourInCup() {
System.out.println("将咖啡倒入杯中");
}
//添加辅料
@Override
protected void addCoundimen() {
System.out.println("添加牛奶和糖");
}
}
//泡茶
public class Tea extends Bevegrage {
//原材料放到杯中
@Override
protected void pourInCup() {
System.out.println("将茶叶放入杯中");
}
//添加辅料
@Override
protected void addCoundimen() {
System.out.println("添加蜂蜜");
}
}
public class Test {
public static void main(String[] args) {
Coffee coffe = new Coffee();
coffe.create();
System.out.println("-----------------");
Tea tea = new Tea();
tea.create();
}
}
运行结果:
烧开水,烧到100度可以起锅了
将咖啡倒入杯中
将开水倒入杯中进行冲泡
添加牛奶和糖
-----------------
烧开水,烧到100度可以起锅了
将茶叶放入杯中
将开水倒入杯中进行冲泡
添加蜂蜜
7.3 应用举例
7.3.1 SpringJDBC
SpringJDBC是java规范,各个数据库厂商自己去实现
1、加载驱动类DriverManager
2、建立连接
3、创建语句集(标准语句集、预处理语句集)
4、执行语句集
5、结果集ResultSet
7.3.2 各种Template类
- MongoTemplate:
org.springframework.data.mongodb.core.MongoTemplate
- RedisTemplate:
org.springframework.data.redis.core.RedisTemplate