泛型和模板设计模式

当两个或多个功能很大一部分实现都一样,只有其中一部分处理逻辑不同的情况下。我们通常都会采用模板设计模式来实现,这样既可以满足功能的需求也可以很好地实现代码的维护。这也正是设计模式的精髓所在。但是,如果有这样一个需求,该如何实现呢?既满足了模板设计模式的条件,也就是说两个或多个功能的总体实现流程是一致的,只是部分处理逻辑上存在差异;但有点特别的是根据不同的功能,返回值类型有所差别。这样的情况下我们可以通过模板设计模式结合泛型来很好地实现相应的功能。

技术要点

我们先来看下模板设计模式的技术点,模板设计模式使用的技术点是:

  • 抽象类:控制程序总体逻辑(骨架)
  • 实现类:继承于抽象类,实现具体差异部分的逻辑

此处要求返回值类型根据不同的业务,返回不同类型的响应信息,因此还需要用到泛型。

  • 泛型于设计模式的结合

具体实现如下:

响应实体泛型的定义

public class Result<T> {
    T response;

    public T getResponse() {
        return response;
    }

    public void setResponse(T response) {
        this.response = response;
    }
}

程序骨架,模板设计模式

public abstract class BaseService<T> {

    /**
     * 定义了程序的主要实现流程-骨架
     * @return
     */
    public Result handle() {
        Result result = new Result();
        method1();
        result.setResponse(method2());
        return result;
    }

    /**
     * 返回值-泛型,根据不同的业务返回不同的响应类型
     * @return
     */
    private T method2() {
        T response = initResponse();//获取子类初始化的响应实例
        System.out.println("BaseService method2");
        return response;
    }

    /**
     * 公共处理业务
     */
    private void method1() {
        System.out.println("BaseService method1");
    }

    /**
     * 响应类型-泛型,提供出去给具体实现类进行初始化
     * @return
     */
    protected abstract T initResponse();
}

模板抽象类需要注意的几个点:

  • BaseService<T>,模板类提供泛型支持
  • Result里的response返回值类型,由子类进行控制
  • 返回值类型,通过提供抽象方法,子类进行初始化来实现。protected abstract T initResponse();

至此,根据不同业务类型返回不同响应类型的模板设计模式的总体框架已经搭建完成了。

差异业务实现类

  • 定义返回值类型
  • 继承于模板抽象类-业务实现类
  • 实现模板抽象类的方法

返回值类型

/**
 *
 * 返回值类型基类,公共部分
 */
public class BaseResponse {
    private int age;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
/**
 *
 * 返回值类型
 */
public class ChinaResponse extends BaseResponse {

    List<String> province;

    public List<String> getProvince() {
        return province;
    }

    public void setProvince(List<String> province) {
        this.province = province;
    }
}
/**
 *
 * 返回值类型
 */
public class AmericaResponse extends BaseResponse {
    List<String> state;

    public List<String> getState() {
        return state;
    }

    public void setState(List<String> state) {
        this.state = state;
    }
}

继承于模板抽象类-业务实现类

/**
 *
 * 业务实现类1
 */
public class ChinaServiceImpl extends BaseService<ChinaResponse> {

    public Result<ChinaResponse> handle() {
        Result result = super.handle();
        return result;
    }

    /**
     * 实现抽象方法,初始化返回值类型
     * @return
     */
    @Override
    protected ChinaResponse initResponse() {
        return new ChinaResponse();
    }
}
/**
 *
 * 业务实现类2
 */
public class AmericaServiceImpl extends BaseService<AmericaResponse> {

    /**
     * 实现抽象方法,初始化返回值类型
     * @return
     */
    @Override
    protected AmericaResponse initResponse() {
        return new AmericaResponse();
    }
}

测试

    public static void main(String[] args) {
        BaseService<ChinaResponse> baseService = new ChinaServiceImpl();
        Result<ChinaResponse> result = baseService.handle();
        ChinaResponse chinaResponse = result.getResponse();
        System.out.println(chinaResponse.toString());

        BaseService<AmericaResponse> americaService = new AmericaServiceImpl();
        Result<AmericaResponse> americaResult = americaService.handle();
        AmericaResponse americaResponse = americaResult.getResponse();
        System.out.println(americaResponse.toString());
    }

测试结果:

BaseService method1
BaseService method2
com.designpatterns.template.generic.response.ChinaResponse@28d93b30
BaseService method1
BaseService method2
com.designpatterns.template.generic.response.AmericaResponse@1b6d3586

总结

通过模板设计模式和泛型的结合,可以非常灵活地处理通用流程和处理逻辑之间的差异;又可以很好地满足不同业务不同返回值类型的需求。

时间: 2024-08-04 10:42:57

泛型和模板设计模式的相关文章

结合泛型与模板的STL.NET探索

模板 开始之前,先来看一个笑话,当问一个C++程序员怎样完成一个给定的任务时,他(她)可能会提供一打或更多的潜在解决方案列表,但又会极其详细地标出每种方案的问题之处,让你不知所措,难以选择.而Visual C++ 2005,通过C++/CLI语言联编,引入了泛型的概念,使C++程序员可进一步提高程序的开发效率.关于 .NET泛型与C++模板,尽管句法上很相似,但泛型与模板是以完全不同的方法实现的,它们之间没有任何的内置兼容性. 说到泛型与模板的差别,相信每个 .NET平台的C++程序员都会问这个

泛型编程深入探索(二) 模板递归与可变参数模版

以构建一个n纬网格为例,讲述模板递归. 首先是一个简单的一纬网格的实现,这个网格实现了规定长度的网格的实例化,并且能够在不同大小的网格类中自由的转型(通过模版嵌套的cast_ctr) (使用到的技术,非类型参数模版,模版嵌套,类模版特例化,模版友元函数) #include <cassert> #include <iostream> using namespace std; template <typename T,int LENGTH> class grid; temp

各位大神,Java的模板模式和单纯的继承有什么不同?好处在哪里?

问题描述 各位大神,Java的模板模式和单纯的继承有什么不同?好处在哪里? 各位大神,Java的模板模式和单纯的继承有什么不同?好处在哪里? 解决方案 模板模式是指定义一个操作中的算法的骨架,而将步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤. 模板模式的优点 模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码. 子类实现算法的某些细节,有助于算法的扩展. 通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合"开放-封闭原则"

java设计模式----模版模式+内部类+设计时间事件处理框架

import java.util.ArrayList; import java.util.List; /**  * 创建一个基于时间驱动的事件  以模板设计模式 +内部类  设计出事件处理的框架  * @author xiaowei  */ //抽象事件类 abstract class Event  {    private   long eventTime   ;   //事件发生    protected long delayTime   ;   //发生间隔据当前时间    Event(l

白话阿里巴巴Java开发手册(编程规约)

最近,阿里巴巴发布了<阿里巴巴Java开发手册>,总结了阿里人多年一线实战中积累的研发流程规范,这些流程规范在一定程度上能够保证最终的项目交付质量,通过限制开发人员的编程风格.实现方式来避免研发人员在实践中容易犯的错误,同样的问题大家使用同样的模式解决,便于后期维护和扩展,确保最终在大规模协作的项目中达成既定目标. 无独有偶,笔者去年在公司里负责升级和制定研发流程.设计模板.设计标准.代码标准等规范,并在实际工作中进行了应用和推广,收效颇丰,也总结了适合支付平台的技术规范,由于阿里巴巴Java

阿里巴巴 Java 开发手册之编程规约(一)-------我的经验

阿里巴巴 Java 开发手册 一.编程规约 (一) 命名规约 1.[强制] 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.(代码规范,易读) 反例: name / __name / $Object / name / name$ / Object$ 2.[强制] 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式. 说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义.注意,即使纯拼音命名方式 也要避免采用.(代码规范,易读) 反例: DaZhePr

阿里巴巴 JAVA 开发手册

阿里巴巴 JAVA 开发手册 1.0.0 阿里巴巴集团技术部 2016.12.7 首次向 Java 业界公开 一. 编程规约(一) 命名规约1. [强制]所有编程相关命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.反例: _name / __name / $Object / name_ / name$ / Object$2. [强制]所有编程相关的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式.说明: 正确的英文拼写和语法可以让阅读者易于理解,避免歧义.注意, 即使

4类多态

    在软考学习的时候,才发现多态不仅仅只有我认识的那么一两种,很多用过的形式原来它们也是多态呀.     首先来看下大图:                     接下来本文将一一举例这些多态,并在末尾做个小对比. 一,简介几种多态     1,泛型                 这个听起来比较高大上,但是大家都用过,例如:           机房收费系统--组合查询中,为了尽可能抽出相同部分,使用T代替.还有转换成list的时候,在定义中指定List of T,使用时: mylist

阿里巴巴 JAVA开发手册 内含大量规范,应用范例.涉及数据库,高并发,集合,索引等等大量干货

  阿里巴巴 JAVA开发手册 Java开发手册 版本号 制定团队 更新日期 备  注 1.0.0 阿里巴巴集团技术部 2016.12.7 首次向Java业界公开 一.编程规约 (一)命名规约 1.  [强制]所有编程相关命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例:  _name  /  __name  /  $Object  /   name_  /  name$  /  Object$ 2.  [强制]所有编程相关的命名严禁使用拼音与英文混合的方式,更不允许直接使