****测试demo    git仓库地址:​​https://github.com/alwaysInRoad/test-strategy-demo1.git​

             

说明:

         本篇博客是建立在实际项目开发。在项目中应用策略模式,分享出来,希望小伙伴们能快速上手策略模式,并能在项目中优化自己的业务。

 

业务场景:在开发公司框架时,我们将项目一些内容与数据库连接放在一个表里,此表用于管理项目。

                  项目管理界面,查看所有表,要获取对应库中的所有表。因此需要执行此句

String sql= "show tables from "+ dataBaseNameNew;

                 但是数据库表存的数据库连接url为:jdbc:mysql://192.168.0.00:3306/xxx  这种格式 (ip地址随意填的,举例为mysql)。

                 于是要截取出url中的xxx。  赋值给  dataBaseNameNew = xxx 。

                 疑问(这里便是策略模式的应用): 如果为oracle数据库,url可能是  jdbc:oracle:thin:@//192.168.2.1:1521/XE

                 这样截取方式就不一样了。在开发项目过程中到底用oracle还是mysql,选择就很多,不可能每次都改源码。所以此处应                   用策略模式,恰到好处。

具体代码:

1、需要编写公共截取接口类:DBPathSub.java

不同的数据库截取方式不一样,不同的业务类都实现此接口

/** 
*
* @author zr
* @date 2018-9-5
* 连接数据库url 处理类:主要截取出数据库名
*
*/
public interface DBPathSub {
//得到库名
public String getDataBaseName(String dbPath);
//得到server
String getServer(String dbPath);
}

2、具体业务类,例如mysql的截取:mysqlDBPathSub.java

这里需要注意,我们规定mysql数据库截取业务类名为:mysqlDBPathSub;oracle为  oracleDBPathSub。名字具有规律性:数据库名+DBPathSub。

import org.springframework.util.StringUtils;

import com.service.dt.DBPathSub;

/**
* mysql数据库连接url具体处理类
* @author zr
* @date 2018-9-5
*
*/
public class mysqlDBPathSub implements DBPathSub {

@Override
public String getDataBaseName(String dbPath) {
if(StringUtils.hasText(dbPath)){
if(dbPath.contains("?")){
return dbPath.substring(dbPath.lastIndexOf("/")+1, dbPath.indexOf("?"));
}else {
return dbPath.substring(dbPath.lastIndexOf("/")+1, dbPath.length());
}
}
return null;
}

@Override
public String getServer(String dbPath) {
if(StringUtils.hasText(dbPath)){
return dbPath.substring(dbPath.indexOf("/")+2,dbPath.lastIndexOf("/"));
}
return null;
}

}

3、策略类:DBPathSubStrategy.java  

/**
* 数据库表明截取策略类
* @author zr
* @date 2018-9-5
*
*/
public class DBPathSubStrategy {
//持有的具体策略的对象
private DBPathSub dbPathSub;
/**
* 构造函数,传入一个具体策略对象
* @param dbPathSub 具体策略对象
*/
public DBPathSubStrategy(DBPathSub dbPathSub) {
super();
this.dbPathSub = dbPathSub;
}
/**
* 策略方法
*/
public String getDataBaseName(String dbPath){
return dbPathSub.getDataBaseName(dbPath);
}

public String getServer(String dbPath){
return dbPathSub.getServer(dbPath);
}
}

 

4、在具体的 service类 业务处理部分,就是策略选择部分。

     开篇提的,数据库存的url连接为 jdbc:mysql://192.168.0.00:3306/xxx 这种格式,所以可以直接从数据库获取我们此刻用的到底是mysql还是oracle或者其它。也可以从配置文件中获取数据库名。

//这句从数据库表中获取url
String dbPath = mapper.getDbPath(code);

//从数据库表中获取数据库类型 (mysql或oracle)
String dbType = mapper.getDbType(code);

//截取查询出的连接数据库的url,截取其中的数据库名
//反射生成具体业务类 这里生成的是mysqlDBPathSub
Class<?> forName = Class.forName(clazz.subSequence(0, clazz.lastIndexOf(".")+1)+dbType.toLowerCase()+"DBPathSub");
Object obj = forName.newInstance();
//调用策略类,这里的 DBPathSubStrategy 类里就拥有了mysqlDBPathSub策略对象
DBPathSubStrategy dbPathSubStrategy = new DBPathSubStrategy((DBPathSub) obj);
//此时调用接口的中的截取方法。执行的是 mysqlDBPathSub中的截取方法
String dataBaseNameNew = dbPathSubStrategy.getDataBaseName(dbPath);
String sql= "show tables from "+ dataBaseNameNew;

总结:我个人理解,策略模式其实就是,利用一个中间类:策略类。来连接策略对象与业务类。策略类不知道业务类用什么策略对象,策略类也不知道具体调什么策略对象,策略类只是拥有父接口对应及调用父接口的方法。这就起到了解耦的作用。 当业务类指定具体策略对象,传给策略类,策略类就知道想要调用的策略对象了。

 

结语:本人所有文章都立志写的简单易懂,戳中问题点。 当然了,简单的同时可能忽略了很多细节与详细,如有不足的地方,还请谅解并指出。