【设计模式系列】7.模板模式和责任链模式

目录

一、模板模式

1、模板模式特点

2、结构分析

3、场景举例 

二、责任链模式

1、责任链模式特点

2、场景举例


一、模板模式

1、模板模式特点

  • 不同场景的处理流程,部分逻辑是通用的,可以放到父类中作为通用实现,而另一部分逻辑是个性化的,需要子类去个性实现;
  • 通常情况下,模板方法模式用于定义构建某个对象的步骤与顺序,或者定义一个算法的骨架;
  • 模板方法使用到的是Java的继承机制,经常在重构项目时用到模板模式;

2、结构分析

一共有两个类:一个抽象类(定义模板方法和基本方法)、一个是具体实现类(继承抽象类,实现个性化的逻辑)。

抽象类AbstractClass:

模板方法:

  • 含义:把基本操作方法组合在一起形成一个总算法或一个总行为的方法;
  • 一个抽象类中可以有任意多个模板方法,而不限于一个;

基本方法:(有三种)

  • 抽象方法:由abstract修饰,抽象类不实现任何的逻辑,由子类重写时实现具体逻辑;
  • 钩子方法:一般抽象类会默认它是个空方法,也可以有实现逻辑,而子类也可以不去重写和实现具体逻辑,命名通常按照doXxx()方式命名的,比如Servlet应用中的doGet()、doPost()、doDestory()等方法;
  • 具体方法:由抽象类实现逻辑,通常是private,final修饰的,因此不会被子类重写。

具体实现类ConcreteClass:

继承AbstractClass,重写相关的抽象方法,实现具体的逻辑。

以做菜为例,无论是做花菜烧肉,还是做酸辣土豆丝,除了第4步不同,其余的都相同,把相同的部分封装在抽象类,不同的部分交由子类去完成个性化的逻辑。

3、场景举例 

比如,构建一个像mybatis中常见的xxxMapper.xml文件,先看一下这类xml文件的整体结构:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.it.demo.mapper.xxxMapper">
    <!--select查询语句-->
    <!--delete删除语句-->
</mapper>

XML中xml、DOCTYPE等部分是通用的,而namespace、sql语句等是需要具体实现的,因此可以用模板方法模式表示出来:

// 定义一个抽象类
public abstract class AbstractXMLBuilder {
    // 模板方法
    public String buildXMLTemplate() {
        StringBuffer sb = new StringBuffer();
        // 相同的部分在抽象父类实现即可,如xml头部、DOCTYPE等
        appendXml(sb);
        appendDOCTYPE(sb);
        // 不同的部分由子类去实现,如namespace、sql语句等
        appendNameSpace(sb);
        appendSelectSql(sb);
        // 尾部关闭标签
        doAppendEnd(sb);
        return sb.toString();
    }
    
    // 具体方法
    private void appendXml(StringBuffer stringBuffer) {
        stringBuffer.append("\n<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
    }
    private void appendDOCTYPE(StringBuffer stringBuffer) {
        stringBuffer.append("<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n");
    }

    // 钩子方法
    protected void doAppendEnd(StringBuffer stringBuffer) {
        stringBuffer.append("</mapper>");
    }

    // 抽象方法
    public abstract void appendNameSpace(StringBuffer stringBuffer);
    public abstract void appendSelectSql(StringBuffer stringBuffer);
}

假如要实现下图的XML文件:

OrderMapperXMLBuilder实现类:

public class OrderMapperXMLBuilder extends AbstractXMLBuilder {
    @Override
    public void appendNameSpace(StringBuffer stringBuffer) {
        stringBuffer.append("<mapper namespace=\"com.xxwei.demo.mapper.OrderMapper\">\n");
    }

    @Override
    public void appendSelectSql(StringBuffer stringBuffer) {
        stringBuffer.append("\t<select id=\"getOrderInfoById\" resultType=\"com.xxwei.demo.entity.po.Order\">\n");
        stringBuffer.append("\t\tSELECT order_id,order_seq,order_name FROM `order` where order_id = #{id}\n");
        stringBuffer.append("\t</select>\n");
    }
    
    // 该方法可以省略不写
    @Override
    public String buildXMLTemplate() {
        return super.buildXMLTemplate();
    }
}

测试:

@Test
void testTemplate() {
    OrderMapperXMLBuilder builder = new OrderMapperXMLBuilder();
    logger.info(builder.buildXMLTemplate());
}

输出结果:

如果再想创建其他的XML,创建一个实现类,继承AbstractXMLBuilder,重写抽象方法即可。

二、责任链模式

1、责任链模式特点

  • 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在一个链条上处理,链条上的受理者处理完毕之后决定是继续往后传递还是中断当前处理流程;
  • 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任;
  • 适用于多节点的流程处理,每个节点完成各自负责的部分,节点之间不知道彼此的存在;
  • 常见的应用:OA工作流系统中分级处理公文审批、Java web中的过滤器Filter等等;

2、场景举例

  • 抽象处理者(AbstractHandler):使子类形成一条链条。
  • 具体处理者(ConcreteHandler):有多个,当前具体对象无法处理时,交由下一个对象处理。
// 定义抽象处理者,使子类形成一条链条
public abstract class AbstractHandler {
    private AbstractHandler handler;

    public AbstractHandler getHandler() {
        return handler;
    }

    public void setHandler(AbstractHandler handler) {
        this.handler = handler;
    }

    public abstract void handlerRequest(String condition);
}

//具体处理者:创建多个,当前具体对象无法处理时,交由下一个对象处理
public class ConcreteHandler1 extends  AbstractHandler{
    @Override
    public void handlerRequest(String condition) {
        if(condition.equals("1")){
            System.out.println("ConcreteHandler1处理....");
        }else{
            System.out.println("ConcreteHandler1不处理,交给其他ConcreteHandler处理....");
            super.getHandler().handlerRequest(condition);
        }
    }
}
public class ConcreteHandler2 extends AbstractHandler{
    @Override
    public void handlerRequest(String condition) {
        if(condition.equals("2")){
            System.out.println("ConcreteHandler2处理....");
        }else{
            System.out.println("ConcreteHandler2不处理,交给其他ConcreteHandler处理....");
            super.getHandler().handlerRequest(condition);
        }
    }
}
public class ConcreteHandler3 extends AbstractHandler{
    @Override
    public void handlerRequest(String condition) {
        if(condition.equals("3")){
            System.out.println("ConcreteHandler3处理....");
        }else{
            System.out.println("ConcreteHandler3不处理,交给其他ConcreteHandler处理....");
            super.getHandler().handlerRequest(condition);
        }
    }
}

测试:

    @Test
    void testChain() {
        AbstractHandler handler1 = new ConcreteHandler1();
        AbstractHandler handler2 = new ConcreteHandler2();
        AbstractHandler handler3 = new ConcreteHandler3();
        // 从handler1开始,在链条传递请求
        handler1.setHandler(handler2);
        handler2.setHandler(handler3);
        // 设置条件
//        handler1.handlerRequest("1");
        handler1.handlerRequest("2");
//        handler1.handlerRequest("3");
    }

结果:

----------------handlerRequest("1")----------------
ConcreteHandler1处理....
----------------handlerRequest("2")----------------
ConcreteHandler1不处理,交给其他ConcreteHandler处理....
ConcreteHandler2处理....
----------------handlerRequest("3")----------------
ConcreteHandler1不处理,交给其他ConcreteHandler处理....
ConcreteHandler2不处理,交给其他ConcreteHandler处理....
ConcreteHandler3处理....

猜你喜欢

转载自blog.csdn.net/qq_29119581/article/details/114883550
今日推荐