初衷 :因架构(开发)场景(需求)而使用设计模式,莫为了使用设计模式而设计架构场景!
学习模板模式后,发现实现方式采用的就是封装、继承、抽象等Java基础知识组合而成, 这些基础我们在开发中早已熟用,只是不自知而已 ~
设计模式共23种,分为三种类型
- 创建型模式:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
- 结构型模式:代理模式、装饰模式、外观模式、享元模式、桥接模式、组合模式、适配器模式
- 行为型模式:观察者模式、策略模式、中介者模式、模版方法模式、命令模式、迭代器模式、职责链模式(责任链模式)、备忘录模式、解释器模式(Interpreter模式)、状态模式、访问者模式
基础概念
主要概念是在父类(基类)中定义一个骨架、框架的流程,内部包含子类的共性方法,同时可以预留钩子方法;当然其具体的实现方式延迟在子类中执行 ~
使用场景
- 多个子类有公有的方法,并且逻辑基本相同
- 重要、复杂的算法, 可以把核心算法设计成模板方法, 周边的相关细节功能则由各个子类实现
- 重构时, 模板模式是一个经常使用的模式, 把相同的代码抽取到父类中,然后通过钩子函数约束其行为
优缺点
优点
- 封装不可变部分(便于维护) - 把不变的行为搬移到基类,去除了子类中的重复代码
- 扩展可变部分 - 子类实现算法的某些细节,有助于算法的扩展
- 通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”
缺点
- 子类数目的增加
- 增加了系统实现的复杂度
- 继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍
角色划分
抽象基类
-
基本方法
一般均为子类的共性方法,因为使用的继承方式,所以一般都用abstract声明该方法,内部具体实现在子类中完成 -
模板方法
一般可以有N和N+1个具体的模板方法,同时对应着N和N+1个框架,主要实现了对基本方法调用的固有逻辑,当有N和N+1个模板方法时往往对应着不同的固有逻辑,大部分的模板方法都加上final关键字, 不允许被覆写, 以防止恶意的操作 -
钩子方法
此方法一般在抽象基类中已经声明,同时并非必须为抽象方法,而且在基类中的模板方法内此方法主用于判断场景导向不同的逻辑;关于具体执行哪个逻辑取决于子类是否重写执行方式(钩子就是给子类一个授权,让子类来决定模板方法的逻辑执行)
具体子类
一般均继承抽象基类,重写抽象方法,具体的实现逻辑都在对应的子类中完成
场景类(使用方式)
使用中我们一般都 new 具体子类,之后通过子类调用父类的模板方法即可 ~
Demo案例
思想
这个Demo主要针对中心思想为"感情之路",大多数人都会经历从恋爱 - 订婚 - 结婚 这样的感情过程,只要你遵循这个过程,那么就是抽象基类中的模板方法了;其中“恋爱、订婚、结婚”我们可以看做是子类的共性方法(基本方法) ,但是针对每个人喜欢什么时间去经历“恋爱、订婚、结婚”又各自不同,所以在这种场景下,我们可以使用模板模式 ~
注意
- 因为我是做Android端的,所以文中的效果输出语句采用的Log输出 ~
- 同因Android是基于Java的语言上进行开发的,所以针对Java开发者无影响 ~
- 后因Android的主输出入口在onCreate生命周期,所以没必要纠结使用的场景所在 ~
常规实现
效果
抽象基类 - LoveParent
/**
* @author MrLiu
* @date 2020/6/30
* desc 抽象基类
*/
public abstract class LoveParent {
//基本方法 - 恋爱
public abstract void love();
//基本方法 - 订婚
public abstract void engagement();
//基本方法 - 结婚
public abstract void married();
//模板方法 - 恋爱、订婚、结婚
public void loveWay() {
this.love();
this.engagement();
this.married();
}
}
具体子类 - Me
import android.util.Log;
/**
* @author MrLiu
* @date 2020/6/30
* desc 具体子类 - Me
*/
public class Me extends LoveParent {
@Override
public void love() {
Log.e("tag", "Me:我认为18岁~恋爱~最合适");
}
@Override
public void engagement() {
Log.e("tag", "Me:我认为28岁~订婚~最合适");
}
@Override
public void married() {
Log.e("tag", "Me:我认为30岁~结婚~最合适");
}
}
具体子类 - You
import android.util.Log;
/**
* @author MrLiu
* @date 2020/6/30
* desc 具体子类 - You
*/
public class You extends LoveParent {
@Override
public void love() {
Log.e("tag", "You:我认为20岁·恋爱·最合适");
}
@Override
public void engagement() {
Log.e("tag", "You:我认为26岁·订婚·最合适");
}
@Override
public void married() {
Log.e("tag", "You:我认为28岁·结婚·最合适");
}
}
场景类
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Me me = new Me();
me.loveWay();
Log.e("tag","-------------------");
You you = new You();
you.loveWay();
}
}
钩子实现
正常的流程都是 恋爱-订婚-结婚,还是不排除很多人喜欢的流程为 恋爱-结婚 ~
而实现此效果有俩种方式,一种为添加勾子方法,一种为新增一种模板方法 ~ 这里讲的是钩子方法
效果
抽象基类 - LoveParent
/**
* @author MrLiu
* @date 2020/6/30
* desc 抽象基类
*/
public abstract class LoveParent {
//基本方法 - 恋爱
public abstract void love();
//基本方法 - 订婚
public abstract void engagement();
//基本方法 - 结婚
public abstract void married();
//钩子方法 - 是否必须订婚
public boolean isHook() {
return true;
}
//模板方法 - 恋爱、订婚、结婚
public void loveWay() {
this.love();
if (isHook()) {
this.engagement();
}
this.married();
}
}
具体子类 - Me
import android.util.Log;
/**
* @author MrLiu
* @date 2020/6/30
* desc 具体子类 - Me
*/
public class Me extends LoveParent {
public boolean hookState = true;
public void setHook(boolean hook) {
this.hookState = hook;
}
@Override
public boolean isHook() {
return hookState;
}
@Override
public void love() {
Log.e("tag", "Me:我认为18岁~恋爱~最合适");
}
@Override
public void engagement() {
Log.e("tag", "Me:我认为28岁~订婚~最合适");
}
@Override
public void married() {
Log.e("tag", "Me:我认为30岁~结婚~最合适");
}
}
具体子类 - You
import android.util.Log;
/**
* @author MrLiu
* @date 2020/6/30
* desc 具体子类 - You
*/
public class You extends LoveParent {
@Override
public void love() {
Log.e("tag", "You:我认为20岁·恋爱·最合适");
}
@Override
public void engagement() {
Log.e("tag", "You:我认为26岁·订婚·最合适");
}
@Override
public void married() {
Log.e("tag", "You:我认为28岁·结婚·最合适");
}
}
场景类
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Me me = new Me();
me.setHook(false);
me.loveWay();
Log.e("tag","-------------------");
You you = new You();
you.loveWay();
}
}