模板方法模式
问题
A模块 和 B模块 完全分开,互相独立,但是重复和相似的代码太多,不便扩展。
解决思路
将重复或相似的代码抽取出来,做成公共的功能,不同的控制就去扩展公共功能,也就是:将相似的运算步骤看做算法的骨架作为父类,具体的不同的步骤放到子类中实现。
模板方法
- 定义
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
父类实现的就是不变的方法和算法的骨架,而需要变化的地方,都通过抽象方法,而子类就通过实现这些抽象方法完成特定的功能。 - 结构
- AbstractClass:抽象类(父类)。定义算法的骨架和原语操作,还可以提供算法通用的实现。(必有)
- ConcreteClass:具体类(子类)。重定义父类的原子操作,完成特定子类的功能。(必有)
- 具体的AbstractClass操作:辅助的公共功能。父类实现某些公共功能,给子类使用。
- 钩子操作:子类选择地覆写父类的具体的操作,已提供新的实现来扩展功能。
- 原语操作:父类的抽象方法,需要子类来实现。(必有)
- Factory Method:父类中,需要某些对象的实例,可以用工厂模式获取,具体的构建对象的实现延迟到子类中。
-
/** * 抽象类 **/ public abstract class AbstractClass { // 原语操作,放到子类去实现 public abstract void PrimitiveOperation1(); public abstract void PrimitiveOperation2(); // 模板方法,定义逻辑的骨架。 public void TemplateMethod() { PrimitiveOperation1(); PrimitiveOperation2();
match(); }
// 具体的操作
public void match()
{
// 公共的实现
}// 工厂模式:创建某个对象,这里用Object代替 public abstract Object createObject();
} /** * 具体类,实现了抽象类中的原语步骤 **/ public class ConcreteClass extends AbstractClass {
@Override public void PrimitiveOperation1() { //具体实现 }
@Override public void PrimitiveOperation2() { //具体实现 }
// 钩子操作
@Override
public void match()
{
// 子类的实现
} }
-
java的回调与模板方法
- 定义
模板方法:在于让其他类来扩展或具体实现在模板(父类)中固定的算法骨架中的某些算法步骤。在标准的模板方法实现中,主要使用继承的方式,使父类在运行期间可以调用到子类中。
在java开发中,还有另一个方法可以实现同样的功能------java回调:通过回调在接口中定义的方法,调用到具体的实现类中的方法。在这种实现中,可以不写子类,而是使用匿名内部类来实现回调方法。 - 结构
- 回调接口:把所有需要扩展的方法定义出来。
- 模板类:
- 不再是抽象类,所有抽象方法删除。
- 模板方法,添加一个参数,传入回调接口。
- 在模板方法实现中,除了模板中固定的实现外,所有可以被扩展的方法,都应通过回调接口进行调用。
- 客户端:需要使用匿名内部类来实现回调接口,并实现其中想要扩展的方法。
/** * 回调接口 **/ public interface InterfaceCallback { // 需要扩展的方法 public void PrimitiveOperation1(); public void PrimitiveOperation2(); // 工厂模式:创建某个对象,这里用Object代替 public Object createObject(); } /** * 模板类 **/ public class TemplateClass { // 模板方法,添加回调接口的入参。 public void TemplateMethod(InterfaceCallback callback) { callback.PrimitiveOperation1(); callback.PrimitiveOperation2(); match(); } // 具体的操作 public void match() { // 实现 } } /** * 客户端 **/ public class Client { // 测试模板方法。 public void TestTemplateMethod() { TemplateClass template = new TemplateClass(); template.TemplateMethod(new InterfaceCallback(){ public void PrimitiveOperation1(){ //具体实现 } public void PrimitiveOperation2(){ //具体实现 } public Object createObject(){ //具体实现 } }); } }
模板方法实现方式:继承/回调 总结
- 回调方式更灵活,因为java是单继承,使用继承方式,子类就不能继承其他对象,而回调基于接口。
- 继承方式,抽象方法和实现的类的关系是在编译时期静态决定的,是类级关系;回调方式,是在运行期间动态决定的,是对象级关系。
- 继承方式更简单点,因为父类提供实现方法,子类不想扩展,不用管;回调方式,回调的接口需要将扩展的所有方法都定义进去,则,实现时,不管扩不扩展,都得实现。
模板方法优缺点
- 优点是实现代码复用:把子类的公共功能提取到模板中实现。
- 缺点是算法骨架不容易升级:模板和子类是非常耦合的,如果变更算法骨架,则相应的子类也可能相应的变化,所以抽取算法骨架,尽量确定不会变化的部分才放到模板中。
简单----伊月海草