大家每到一家公司都会发现,每个公司都会有一个规范,比如说请假流程规范,代码规范等等。每个公司都有这个流程,只是里面的具体执行条件不一样而已。
成都创新互联主营广水网站建设的网络公司,主营网站建设方案,成都App定制开发,广水h5小程序开发搭建,广水网站营销推广欢迎广水等地区企业咨询
在设计模式中的模版方法模式,也是可以理解为一种规范模版。主要是提升我们代码的复用性,以及扩展等问题。
这样的模板方法在我们当舔狗跟妹妹们聊天的时候也是可以用到的,比如这样一个模板:
“宝,XXXX了,XXXX什么XX?X你的XXX”
当我拿到这样一个模板的时候,我就可以举一反三直接套用了,我们直接填参数就可以了,比如:
“宝,我打疫苗了,打的什么苗 ,爱你的每一秒 ”
“宝,我做核酸了,做的什么酸,得不到你的心酸”
“宝,今天去输液了,输的什么液,想你的夜”
...........
好了言归正传,在框架中模版方法模式也是很常见的。
今天就具体来聊聊设计模式中行为型设计模式中模版方法模式。
设计模式系列往期文章:
还是老规矩从上图五个方面来分别具体和大家聊聊模版方法模式
模版方法模式的定义以及目的?
结构图:
整个结构图看起来还是很简单的,但是还是要理解设计模式解决什么问题。
代码实现?还是举例吧。
还是以上面的请假举例吧,假设现在A公司请假需要直属领导审批以及通知HR有人请假了就可以了,B公司需要直属领导,部门负责人审批最后通知HR,方能完成整个请假流程。那作为OA办公流程怎么去处理这个问题嘛?直接看代码实现吧!
- public abstract class AskForLeaveFlow {
- // 一级组长直接审批
- protected abstract void firstGroupLeader(String name);
- // 二级组长部门负责人审批
- protected void secondGroupLeader(String name) {
- }
- // 告知HR有人请假了
- private final void notifyHr(String name) {
- System.out.println("当前有人请假了,请假人:" + name);
- }
- // 请假流模版
- public void askForLeave(String name) {
- firstGroupLeader(name);
- secondGroupLeader(name);
- notifyHr(name);
- }
- }
首先还是定义一个请假流程,其中:
最后一个askForLeave请假流程方法,把以上模版方法串起来
- public class CompanyA extends AskForLeaveFlow {
- @Override
- protected void firstGroupLeader(String name) {
- System.out.println("CompanyA 组内有人请假,请假人:" + name);
- }
- }
- public class CompanyB extends AskForLeaveFlow {
- @Override
- protected void firstGroupLeader(String name) {
- System.out.println("CompanyB 组内有人请假,请假人:" + name);
- }
- @Override
- protected void secondGroupLeader(String name){
- System.out.println("CompanyB 部门有人请假,请假人:" + name);
- }
- }
在CompanyA以及CompanyB中,secondGroupLeader二级领导可以选择重写或者不重写,这个类模版方法简称为钩子方法。
- public class testTemplate {
- public static void main(String[] args) {
- // 公司A请假流程模版
- AskForLeaveFlow companyA = new CompanyA();
- companyA.askForLeave("敖丙");
- // 结果:CompanyA 组内有人请假,请假人:敖丙
- // 当前有人请假了,请假人:敖丙
- AskForLeaveFlow companyB = new CompanyB();
- companyB.askForLeave("敖丙");
- // 结果:CompanyB 组内有人请假,请假人:敖丙
- // CompanyB 部门有人请假,请假人:敖丙
- // 当前有人请假了,请假人:敖丙
- }
- }
最后就是看测试dome结果了。companyA和companyB分别输出了对应的请假流程。
细心的同学可能已经发现了,做为模版方法中里面除了可以有抽象方法外,还可以有具体的实现方法以及钩子方法。
所以大家在应用的过程可以多考虑考虑在内部定义模版方法时,应该定义成抽象方法还是其它的。
模版方法模式在我们常见的Java的框架中也是非常常见的,只是可能我们平时没有注意到这一点而已。
第一个:首先我们学SpringMVC的时候,最开始都会写一些Servlet来作为处理一些post或者get请求等。
这里直接看这个源码大家就可以发现这也是直接使用模版方法模式的思想,期间在HttpServlet 继承GenericServlet中也还是模版方法的体现,这说明了可以多次抽象构建模版。
第二个:常见问的文件流中,Java IO 类中的InputStream、OutputStream、Reader、Writer等都能看到模版方法模式的身影。
上面是我贴出的部分InputStream的源码,主要看这个read模版方法,也就是模版方法模式的体现。
当然IO类中还有很多其他的,我就不一一贴源码出来了,感情兴趣的同学,可以自己打开源码了解了解。
首先需要理解模版方法它是为了增加代码的复用性,以及扩展性而存在的,所以本着这个思想我还是给大家举一个例子吧。
之前写责任链模式最后给大家举例商品详情,这次还是用商品详情,但是用模版方法模式来实现这个问题,理解为商详2.0版本。
商品详情展示我们可以是分模块展示的,比如头图,商品信息,sku信息,配送地址,分期付费等等。
流程图:
可以看到一个请求过来,可以有模块组装器选择组装返回结果。
接下来直接看代码吧
- public abstract class AbstractTemplateBlock
{ - // 组装结果
- public T template(ModelContainer modelContainer) {
- T block = initBlock();
- try {
- this.doWork(modelContainer, block);
- } catch (Exception e) {
- // 可以选择捕获异常,是中断流程,还是只打印日志,不中断流程
- }
- return block;
- }
- // 初始化构建返回结果模型
- protected abstract T initBlock();
- // 定义抽象模版
- protected abstract void doWork(ModelContainer modelContainer, T block) throws Exception;
- }
还是先创建模版Block
- @Component
- public class ItemInfoBlock extends AbstractTemplateBlock
{ - @Override
- protected ItemInfoBlock.ItemInfo initBlock() {
- return new ItemInfoBlock.ItemInfo();
- }
- // 模拟业务逻辑,组装返回商品信息模块数据
- @Override
- protected void doWork(ModelContainer modelContainer, ItemInfo block) throws Exception {
- block.setItemId(123L);
- block.setItemName("测试");
- }
- @Data
- public static class ItemInfo {
- private Long itemId;
- private String itemName;
- }
- }
这里只写了一个ItemInfoBlock,其他的模块也是这一样的写法,所以就不全写出来了。
- public static void main(String[] args) {
- // 1.模拟获取SpringBean
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
- ItemInfoBlock itemInfoBlock = (ItemInfoBlock) applicationContext.getBean("itemInfoBlock");
- // 2. ModelContainer可以理解为贯穿上下文中的请求参数,或者一些组装数据需要的预加载数据
- ModelContainer modelContainer = new ModelContainer();
- // 3. 获取返回结果
- ItemInfoBlock.ItemInfo itemInfo = itemInfoBlock.template(modelContainer);
- System.out.println(JSON.toJSONString(itemInfo));
- // 结果:{"itemId":123,"itemName":"测试"}
- }
最后就是看测试demo了,可以看到再每一个模块中都是有一个AbstractTemplateBlock,内部包含doWork抽象方法,由子类去实现当前自己的业务逻辑。
同时第三步获取返回结果时,我只是单独列出来,大家可以根据实际情况还能做改造。比如说返回map结构等 mapKey 是模块名称,value是数据。
当前这种组装商品详情的模式也是比较常见的一种方式。代码的复用性高,同时扩展性也有一定的体现,符合模版方法模式的思想。
模版方法模式的特点大家应该也能体会到了,适用场景还是为了增加代码的复用性,以及扩展性。
还是那句话存在即合理,不要因设计模式而在写代码时强行嵌套。合理的学习每种设计模式适合场景,解决什么问题。
当前题目:设计模式之模版方法模式
转载来于:http://www.csdahua.cn/qtweb/news46/70396.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网