/**
* 实现日志策略的抽象模板,实现给消息添加时间
*/
public abstract class LogStrategyTemplate implements LogStrategy{
public final void log(String msg) {
//第一步:给消息添加记录日志的时间
DateFormat df = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss SSS");
msg = df.format(new java.util.Date())+" 内容是:"+ msg;
//第二步:真正执行日志记录
doLog(msg);
}
/**
* 真正执行日志记录,让子类去具体实现
* @param msg 需记录的日志信息
*/
protected abstract void doLog(String msg);
}
(3)这个时候那两个具体的日志算法实现也需要做些改变,不再直接实现策略接口了,而是继承模板,实现模板方法了。这个时候记录日志到数据库的类,示例代码如下:
/**
* 把日志记录到数据库
*/
public class DbLog extends LogStrategyTemplate{
//除了定义上发生了改变外,具体的实现没变
public void doLog(String msg) {
//制造错误
if(msg!=null && msg.trim().length()>5){
int a = 5/0;
}
System.out.println("现在把 '"+msg+"' 记录到数据库中");
}
}
同理实现记录日志到文件的类如下:
/**
* 把日志记录到数据库
*/
public class FileLog extends LogStrategyTemplate{
public void doLog(String msg) {
System.out.println("现在把 '"+msg+"' 记录到文件中");
}
}
(4)算法实现的改变不影响使用算法的上下文,上下文跟前面一样,示例代码如下:
/**
* 日志记录的上下文
*/
public class LogContext {
/**
* 记录日志的方法,提供给客户端使用
* @param msg 需记录的日志信息
*/
public void log(String msg){
//在上下文里面,自行实现对具体策略的选择
//优先选用策略:记录到数据库
LogStrategy strategy = new DbLog();
try{
strategy.log(msg);
}catch(Exception err){
//出错了,那就记录到文件中
strategy = new FileLog();
strategy.log(msg);
}
}
}
(5)客户端跟以前也一样,示例代码如下:
public class Client {
public static void main(String[] args) {
LogContext log = new LogContext();
log.log("记录日志");
log.log("再次记录日志");
}
}
运行一下客户端再次测试看看,体会一下,看看结果是否带上了时间。
通过这个示例,好好体会一下策略模式和模板方法模式的组合使用,在实用开发中是很常见的方式。
3.5 策略模式的优缺点
定义一系列算法
策略模式的功能就是定义一系列算法,实现让这些算法可以相互替换。所以会为这一系列算法定义公共的接口,以约束一系列算法要实现的功能。如果这一系列算法具有公共功能,可以把策略接口实现成为抽象类,把这些公共功能实现到父类里面,对于这个问题,前面讲了三种处理方法,这里就不罗嗦了。
避免多重条件语句
根据前面的示例会发现,策略模式的一系列策略算法是平等的,可以互换的,写在一起就是通过if-else结构来组织,如果此时具体的算法实现里面又有条件语句,就构成了多重条件语句,使用策略模式能避免这样的多重条件语句。
如下示例来演示了不使用策略模式的多重条件语句,示例代码如下:
public class OneClass {
/**
* 示范多重条件语句
* @param type 某个用于判断的类型
*/
public void oneMethod(int type){
//使用策略模式的时候,这些算法的处理代码就被拿出去,
//放到单独的算法实现类去了,这里就不再是多重条件了