只有光头才能变强。
文本已收录至我的github仓库,欢迎star:https://github.com/zhongfucheng3y/3y
在上一篇有读者说,一分钟就看完门面模式了,所以今天的标题就取《一分钟学会模板方法模式》
回顾前面所写过的设计模式:
无论是面试还是个人的提升,设计模式是必学的。今天来讲解模板方法模式~
大家都知道,我每次写原创技术文章,开头总会有“只有光头才能变强”。我当然不可能每次写文章的时候都去复制这句话(因为这样太麻烦了)。
我有自己的写作模板,给大家看一下:
前言和最后都是固定下来的,至于第一点和第二点就得看是写什么文章,写不同的文章对应的内容也是不一样的。
每次我写文章的时候,只要在这个模板上添加我自己想写的东西就好了,就不用每次都复制一遍相同的内容,这样就大大减少我的工作量啦。
代码来源于生活,同样地我可以将我写文章的过程用代码来描述,大家来看一下。
3y每篇文章都会有“前言”和“最后”的内容,3y把这两个模块写出来了。
// 3y的文章模板 public class java3ywritearticle { // 前言 public void introduction() { system.out.println("只有光头才能变强"); } // 最后 public void thelast() { system.out.println("关注我的公众号:java3y"); } }
3y写文章的时候,3y可能就会这样使用:
// 3y写文章 public static void main(string[] args) { java3ywritearticle writearticle = new java3ywritearticle(); // 前言 writearticle.introduction(); // 实际内容 system.out.println("大家好,我是3y,今天来给大家分享我写的模板方法模式"); // 最后 writearticle.thelast(); }
这样是可以完成3y写文章的功能,但是这样做好吗?这时候3y女朋友也想写文章,她的文章同样也想有“前言”和“最后”两个模块,所以3y女朋友的文章模板是这样的:
// 3y女朋友的文章模板 public class java3ygfwritearticle { // 前言 public void introduction() { system.out.println("balabalabalalabalablablalab"); } // 最后 public void thelast() { system.out.println("balabalabalalabalablablalab"); } }
那3y女朋友写文章的时候,可能也会这样使用:
// 3y女朋友写文章 public static void main(string[] args) { java3ygfwritearticle java3ygfwritearticle = new java3ygfwritearticle(); // 前言 java3ygfwritearticle.introduction(); // 实际内容 system.out.println("3y是傻子,不用管他"); // 最后 java3ygfwritearticle.thelast(); }
可以发现3y和3y女朋友要写文章的时是要重复调用introduction();
和thelast();
。并且,3y的文章模板和3y女朋友的文章模板中的“前言”和“最后”只是实现内容的不同,却定义了两次,明显就是重复的代码。面对重复的代码我们会做什么?很简单,抽取出来!
于是我们就可以抽取出一个通用的writearticle(为了方便调用,我们还将写文章的步骤封装成一个方法):
// 通用模板 public abstract class writearticle { // 每个人的“前言”都不一样,所以抽象(abstract) protected abstract void introduction(); // 每个人的“最后”都不一样,所以抽象(abstract) protected abstract void thelast(); // 实际要写的内容,每个人的“实际内容”都不一样,所以抽象(abstract) protected abstract void actualcontent(); // 写一篇完整的文章(为了方便调用,我们将这几个步骤分装成一个方法) public final void writeancompletearticle() { // 前言 introduction(); // 实际内容 actualcontent(); // 最后 thelast(); } }
所以,3y的模板就可以继承通用模板,在通用模板上实现自己想要的就好了:
// 3y的文章模板 public class java3ywritearticle extends writearticle { // 前言 @override public void introduction() { system.out.println("只有光头才能变强"); } // 最后 @override public void thelast() { system.out.println("关注我的公众号:java3y"); } @override protected void actualcontent() { system.out.println("大家好,我是3y,今天来给大家分享我写的模板方法模式"); } }
同样地,3y女朋友的文章模板也是类似的:
// 3y女朋友的文章模板 public class java3ygfwritearticle extends writearticle { // 前言 @override public void introduction() { system.out.println("balabalabalalabalablablalab"); } // 最后 @override public void thelast() { system.out.println("balabalabalalabalablablalab"); } @override protected void actualcontent() { system.out.println("3y是傻子,不用管他"); } }
想要真正写文章的时候就十分方便了:
// 3y写文章 public static void main(string[] args) { writearticle java3ywritearticle = new java3ywritearticle(); java3ywritearticle.writeancompletearticle(); } // 3y女朋友写文章 public static void main(string[] args) { writearticle java3ygfwritearticle = new java3ygfwritearticle(); java3ygfwritearticle.writeancompletearticle(); }
要点:
嗯,上面的就是模板方法模式,就这么简单!
《设计模式之禅》:
定义一个操作中的算法框架,而将一些步骤延迟到子类中。使子类可以不改变一个算法的结构即可重定义该算法的某些步骤。
根据我们上面的例子,来讲讲这段话的含义:
比如3y在文章模板中的introduction()
改了,“只有充钱才能变强”
@override public void introduction() { system.out.println("只有充钱才能变强"); }
我们没有碰过writeancompletearticle()的代码,但再次调用这个方法的时候,具体的实现就会发生改变(因为writeancompletearticle受子类的具体实现影响)
下面我们看一下模板方法模式的通用类图:
在模板方法模式中,也有几个术语,根据我们的例子中的注释,我给大家介绍一下:
// 抽象模板类 public abstract class writearticle { // 基本方法 protected abstract void introduction(); // 基本方法 protected abstract void thelast(); // 基本方法 protected abstract void actualcontent(); // 模板方法 public final void writeancompletearticle() { introduction(); actualcontent(); thelast(); } } // 具体模板类 public class java3ywritearticle extends writearticle { // 实现基本方法 @override public void introduction() { system.out.println("只有充钱才能变强"); } // 实现基本方法 @override public void thelast() { system.out.println("关注我的公众号:java3y"); } // 实现基本方法 @override protected void actualcontent() { system.out.println("大家好,我是3y,今天来给大家分享我写的模板方法模式"); } }
优点:
缺点:
最经典的就是juc包下的aqs(abstractqueuedsynchronizer)了。aqs是什么?
aqs其实就是一个可以给我们实现锁的框架。内部实现的关键是:先进先出的队列、state状态
我们可以看一下aqs定义的acquire()
public final void acquire(int arg) { if (!tryacquire(arg) && acquirequeued(addwaiter(node.exclusive), arg)) selfinterrupt(); }
acquire()
相当于模板方法,tryacquire(arg)
相当于基本方法。
模板方法模式也很简单呀,一个抽象类有基本方法(等着被子类实现的方法),有模板方法(对外暴露、调用基本方法、定义了算法的框架),那就完事了。
推荐阅读和参考资料:
乐于分享和输出干货的java技术公众号:java3y。关注即可领取海量的视频资源!
精彩回顾:
觉得我的文章写得不错,不妨点一下赞!
如对本文有疑问, 点击进行留言回复!!
【java基础】面试常见问题:类和对象,封装继承多态,final关键字,static关键字,类加载过程,双亲委派模型
荐 Java语言基础之JDK1.8新特性(Lambda表达式、函数式接口、Stream流、新的日期API)
网友评论