如约而至,开始模板方法模式学习的旅途……
一、模板方法模式定义
模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构即可重新定义该算法的某些特定步骤。
二、模板方法模式使用场景
1、使用场景
(1)、当子类中有一些不变的通用的算法时,可以把这些提升到父类,减少代码重复,特定子类相关步骤在子类中完成。
2、类图
模板方法模式URL包括两个角色:抽象模板类和实现类

AbstractClass 模板方法类模板模板方法定义类算法骨架,operation 运算方法被延迟到子类中实现。
ConcreteClass 实现抽象方法、重写父类方法完成算法中与特定子类相关的步骤。
模板方法类中去了定义模板方法,抽象方法外还可以定义通用方法(减少代码重复)、钩子方法(子类扩展)来服务子类。
三、代码展示
1、模板方法类
public abstract class AbstractClass {
/**
* 模板方法定义算法流程
*/
public void template() {
//起床
operation1();
//洗漱
operation2();
//跑步
operation3();
//早饭
operation4();
//上班
operation5();
}
/**
* 算法中所有子类公工操作
*/
public void operation1() {
System.out.println("起床");
}
/**
* 算法中所有子类公工操作
*/
public void operation2() {
System.out.println("洗漱");
}
/**
* 算法中默认操作
*/
public void operation3() {
System.out.println("室内跑步");
}
/**
* 算法中子类特定操作
*/
public abstract void operation4();
/**
* 算法中子类公共操作
*/
public void operation5() {
System.out.println("上班");
}
}
2、实现类
(1)、实现抽象类
public class ConcreteClass extends AbstractClass {
@Override
public void operation4() {
System.out.println("早饭喝粥");
}
}
(2)、实现抽象类,重写父类方法
public class ConcreteClass2 extends AbstractClass {
@Override
public void operation3() {
System.out.println("室外跑步");
}
@Override
public void operation4() {
System.out.println("早饭吃面");
}
}
在看看项目中使用到的模板方法模式
多个MQ消费者创建消费消息:
(1)、获取MQ配置属性(group、nameServer、topic、tag……)
(2)、创建消费者设置消费者属性
(3)、注册监听类
(4)、遍历消息对象
(5)、处理消息
在这样的一个流程中,获取MQ配置属性和各个对象处理消息是需要按照自己需求进行处理,其他的流程都是一样的,所以我们可以使用模板方法模式来实现这样的一个流程。
1、模板方法类
public abstract class AbstractConsumer {
/**
* 配置文件
*/
private Map<String, String> properties = Maps.newHashMap();
/**
* 消费对象
*/
DefaultMQPushConsumer consumer = null;
/**
* 配置属性按照子类配置获取
*
* @return
*/
abstract Map<String, String> getProperties();
/**
* 具体子类消息处理方法
*
* @param key
* @param messageBody
* @return
*/
abstract Boolean handler(String key, String messageBody);
/**
* 这里相当于是模板方法
*/
public void listener() {
try {
// 配置属性获取
properties = getProperties();
// 对象
consumer = new DefaultMQPushConsumer(properties.get("group"));
// 属性设置……
consumer.setNamesrvAddr(properties.get("nameServer"));
// 注册监听
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (int i = 0; i < msgs.size(); i++) {
MessageExt msgExt = msgs.get(i);
String key = msgExt.getMsgId();
String msgBody = new String(msgExt.getBody());
// 消息处理
handler(key, msgBody);
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
} catch (MQClientException e) {
logger.error("mqProperty:{}", JSON.toJSONString(mqProperty), e);
}
}
}
2、实现类
(1)、B端数据消费
public class Customer2B extends AbstractConsumer {
@Override
protected Map<String, String> getProperties() {
Map<String, String> param = Maps.newHashMap();
param.put("group", "ToB");
param.put("nameServer", "127.0.0.1:8090");
return param;
}
@Override
Boolean handler(String key, String messageBody) {
//数据入库B
return true;
}
}
(2)、C端数据消费
public class Customer2C extends AbstractConsumer {
@Override
protected Map<String, String> getProperties() {
Map<String, String> properties = Maps.newHashMap();
properties.put("group", "ToC");
properties.put("nameServer", "127.0.0.1:8090");
return properties;
}
@Override
Boolean handler(String key, String messageBody) {
//数据入库C
return true;
}
}
四、优点
1、它把不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
2、它在父类中提取了公共的部分代码,便于代码复用。
3、部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
654

被折叠的 条评论
为什么被折叠?



