堕落了几天,本来之前就应该把设计模式的笔记全部写完的,但是因为“懒惰使我快乐”的作用下,还是没有实现目标,但是今天呢,还是要开启第三种设计模式行为型设计模式的博文记录。之前我们学了第一种设计模式创建型的五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;第二种设计模式结构型七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。现在要开启第三种设计模式行为型十一种:这十一种分为四类,父类与子类:策略模式、模板方法模式;两个类自检:观察者模式、迭代子模式、责任链模式、命令模式;类的状态:备忘录模式、状态模式;通过中间类:访问者模式、中介者模式、解释器模式。这里来学习第三种设计模式中的父类与子类的第一种:策略模式,我们开始学习吧。
1、策略模式
策略模式定义了一系列的算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。
2、例子
这里举一个使用数据库,假如我们要使用数据库的查询结构,如果按照一般的使用方法,会如下所示:
public void select(String name) {
if("ORACLE".equals(name)) {
System.out.println("Oracle数据库的查询方法");
}else if("MYSQL".equals(name)) {
System.out.println("MySQL数据库的查询方法");
}else {
System.out.println("请选择数据库的查询方法");
}
}
如果我们现在有个需求,需要新加一个REDIS的查询,那么我们作为程序员能够做的是在这个方法上多加一个if语句,然后接下来要测试测一下有没有影响到ORACLE和MYSQL的正常使用,完全违背了设计原则:对扩展开放,对修改关闭。并且每次都要改动这个方法,会导致这个方法很庞大。此时我们就可以用策略模式来解决这个办法。
3、UML
4、组成
组成 | 作用 |
---|---|
抽象策略角色 | 这个是一个抽象的角色,通常情况下使用接口或者抽象类去实现,也就是上面UML中的DBStrategy |
具体策略角色 | 包装了具体的算法和行为,实现了抽象策略角色,对应上面的UML就是OracleDBStrategy、MySQLDBStrategy |
策略上下文 | 内部会持有一个抽象策略角色的引用,给哭护短调用 |
5、抽象策略角色DBStrategy
/**
* 数据库策略接口
* @author suibibk.com
*
*/
public interface DBStrategy {
//查询数据
public void select();
}
这里的算法目标都是查询数据。
6、具体策略角色OracleDBStrategy和MySQLDBStrategy
/**
* 具体的策略实现
* @author suibibk.com
*/
public class OracleDBStrategy implements DBStrategy {
@Override
public void select() {
System.out.println("用Oracle数据库查询数据成功");
}
}
/**
* 具体的策略实现
* @author suibibk.com
*/
public class MySQLDBStrategy implements DBStrategy {
@Override
public void select() {
System.out.println("用MySQL数据库查询数据成功");
}
}
7、策略上下文StrategyContext
/**
* 策略上下文
* @author suibibk.com
*
*/
public class StrategyContext {
//持有一个策略实现的引用
private DBStrategy strategy;
//使用构造器注入具体的策略类
public StrategyContext(DBStrategy strategy) {
this.strategy=strategy;
}
//执行策略
public void exec() {
strategy.select();
}
}
8、客户端使用者Test
/**
* 测试类
* @author suibibk.com
*
*/
public class Test {
public static void main(String[] args) {
//我们要用Oracle数据库
StrategyContext context1 = new StrategyContext(new OracleDBStrategy());
context1.exec();
//我们要用MySQL
StrategyContext context2 = new StrategyContext(new MySQLDBStrategy());
context2.exec();
//假如我们要用redis,那么不用改动Oracle和MySQL,直接新建一个RedisDBStrategy类实现DBStrategy即可。
//完美的实现了对扩展开放,对修改关闭的原则
}
}
运行Test,将会输出如下内容
用Oracle数据库查询数据成功
用MySQL数据库查询数据成功
因此我们将多种if的模式用策略模式的方法优化了,完美的实现了向扩展开放,向修改关闭,后面就算要加各种其他数据库的查询的算法也不需要修改原来的算法。
9、优缺点
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
总结
总体来说,第三种设计模式下的第一类的第一种还是很简单也很实用的,还有很多场景都会用的上,比如银行不同等级的客户办理同一个业务,但是优惠是不同的,就可以用策略模式。 感叹一句,写博文真的很难,不过为了以后看笔记方便还是需要认真写。