文档章节

spring常用模式--模板模式

o
 osc_g8254g7s
发布于 2019/08/19 17:06
字数 1398
阅读 11
收藏 0

精选30+云产品,助力企业轻松上云!>>>

引入:这几天在看一本讲spring源码的书《SPRING技术内幕》里面在讲加载配置文件的时候,可以有不同的加载方式,如根据文件系统目录加载配置文件(FileSystemXmlApplicationContext),类路径加载配置文件(ClassPathXmlApplicationContext),以及根据项目上下文目录(XmlWebApplicationContext)加载配置文件。这个在加载的过程中就使用了模板设计模式,所以就来学习下模板设计模式。

1. 模板设计模式在书中定义:

  定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。

  通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。

2. 如下网上找到的一个模板模式的类图:

  抽象父类(AbstractClass):实现了模板方法,定义了算法的骨架。

  具体类(ConcreteClass):实现抽象类中的抽象方法,即不同的对象的具体实现细节。

    

3. 实例说明

  来举个例子: 比如我们做菜可以分为三个步骤 (1)备料 (2)具体做菜 (3)盛菜端给客人享用,这三部就是算法的骨架 ;然而做不同菜需要的料,做的方法,以及如何盛装给客人享用都是不同的这个就是不同的实现细节。

  下来我们就代码实现如下

 a. 先来写一个抽象的做菜父类:  

复制代码
public abstract class DodishTemplate {    
    /**
     * 具体的整个过程
     */
    protected void dodish(){
        this.preparation();
        this.doing();
        this.carriedDishes();
    }
    /**
     * 备料
     */
    public abstract void preparation();
    /**
     * 做菜
     */
    public abstract void doing();
    /**
     * 上菜
     */
    public abstract void carriedDishes ();
}
复制代码

 b. 下来做两个番茄炒蛋(EggsWithTomato)和红烧肉(Bouilli)实现父类中的抽象方法

复制代码
/**
 * 西红柿炒蛋
 * @author aries
 */
public class EggsWithTomato extends DodishTemplate{

    @Override
    public void preparation() {
        System.out.println("洗并切西红柿,打鸡蛋。");
    }

    @Override
    public void doing() {
        System.out.println("鸡蛋倒入锅里,然后倒入西红柿一起炒。");
    }

    @Override
    public void carriedDishes() {
        System.out.println("将炒好的西红寺鸡蛋装入碟子里,端给客人吃。");
    }

}
复制代码
复制代码
/**
 * 红烧肉
 * @author aries
 *
 */
public class Bouilli extends DodishTemplate{

    @Override
    public void preparation() {
        System.out.println("切猪肉和土豆。");
    }

    @Override
    public void doing() {
        System.out.println("将切好的猪肉倒入锅中炒一会然后倒入土豆连炒带炖。");
    }

    @Override
    public void carriedDishes() {
        System.out.println("将做好的红烧肉盛进碗里端给客人吃。");
    }

}
复制代码

  c. 在测试类中我们来做菜:

复制代码
public class App {
    public static void main(String[] args) {
        DodishTemplate eggsWithTomato = new EggsWithTomato();
        eggsWithTomato.dodish();
        
        System.out.println("-----------------------------");
        
        DodishTemplate bouilli = new Bouilli();
        bouilli.dodish();
    }
}
复制代码

 这样我们就实现了使用模板模式的一个完整的实例。

4. 在书本上看到过这么一个例子:

 去银行办业务,如取钱,存钱或者办卡等,基本都需要三个大的步骤(骨架),首先 (1)取号 (2)办具体业务 (3)服务评价打分,然后这三个步骤就可以抽取到父类中进行定义,(1)取号 (3)服务打分是相同操作,可以直接在父类总实现,然后(2)办具体的业务各不相同需要在子类中实现。如下我画个类图:

    takeNumber(取号),trabsact(具体业务),evaluate(评价),process(骨架方法)。

5. 模板设计模式常在数据库操作中使用,我现在使用模板模式做一个JDBC的查询模板:

  (1) 抽象查询父类 

复制代码
public abstract class AbstractDao {

    /**
     * 查询
     * @param sql
     * @param params
     * @return
     */
    protected Object find(String sql, Object[] params) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Object obj = null;
        try {
            conn = JDBCUtils.getConnection();
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i + 1, params[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()) {
                obj = rowMapper(rs);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.free(rs, ps, conn);
        }
        return obj;
    }
    
protected abstract Object rowMapper(ResultSet rs) throws SQLException;

//同时可以添加 insert ,update 等方法 }
复制代码

 (2)具体的UserDao

复制代码
/**
 * userDao
 * 
 * @author aries
 *
 */
public class UserDao extends AbstractDao {

    public User findUser(int userId) {
        String sql = "select * from t_user where userId = ?";
        Object[] params = new Object[] { userId };
        Object user = super.find(sql, params);
        System.out.println((User) user);
        return (User) user;
    }

    @Override
    protected Object rowMapper(ResultSet rs) throws SQLException {
        User user = new User();
        user.setId(rs.getInt("userId"));
        user.setName(rs.getString("name"));
        user.setAge(rs.getInt("age"));
        user.setSex(rs.getString("sex"));
        user.setAddress(rs.getString("address"));
        return user;
    }
}
复制代码

 (3)以上代码中用到的User类和JDBCUtil

复制代码
public class JDBCUtils {
    private static String url = "jdbc:mysql://localhost:3306/jdbcstudy";
    private static String user = "root";
    private static String password = "123";

    private JDBCUtils() {
    }

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
    
    public static void free(ResultSet rs, PreparedStatement ps, Connection conn){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(ps != null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
复制代码
复制代码
/**
 * 用户类
 * 
 * @author aries
 *
 */
public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
    private String address;
        
    //set...get省略    
}
复制代码

 如上就使用模板模式做的查询,父类中做了算法骨架,子类中具体实现算法中的不同部分。

6. 模板模式的优点

 (1)具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。

 (2)代码复用的基本技术,在数据库设计中尤为重要。

 (3)存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。

7. 不足

    每个不同的实现都需要定义一个子类,会导致类的个数增加,系统更加庞大。

原文引用自:https://www.cnblogs.com/qq-361807535/p/6854191.html

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Spring Boot 五种热部署方式,再也不用老重启了!

org.springframework.boot spring-boot-devtools

郝光明
03/14
0
0
《应用SpringBoot改变web应用开发模式》论文笔记

《应用SpringBoot改变web应用开发模式》论文笔记 一、基本信息 标题:应用SpringBoot改变web应用开发模式 来源:哈尔滨学院,黑龙江 哈尔滨 关键字::SpringBoot;JavaEE;web 开发;Docker ...

osc_r33mp6vv
2019/12/15
7
0
面试题:你简历中写到熟悉Spring源码,那你给我说说它用到了那些设计模式?

Spring作为业界的经典框架,无论是在架构设计方面,还是在代码编写方面,都堪称行内典范。好了,话不多说,开始今天的内容。 spring中常用的设计模式达到九种。 模板方法(Template Method)...

我最喜欢三大框架
2019/05/22
12
0
Spring中使用的设计模式

  Spring框架是每个java程序猿入门级的框架也是最重要的框架,而Spring中也采用了很多的设计模式,这些也会成为我们面试过程中经常会问到的问题,所以本文就整理出Spring中具体使用的哪些设...

osc_0ypeszdl
2019/03/06
5
0
Thymeleaf入门基础

一.简介   1.thymeleaf优点     ①是一个支持html原型的自然引擎,它在html标签增加额外的属性来达到模板+数据的展示方式,由于浏览器解释html时,忽略未定义的标签属性,因此thymele...

osc_1rwvn3a2
2018/01/02
2
0

没有更多内容

加载失败,请刷新页面

加载更多

敖丙20 张图揭开内存管理的迷雾

前言 之前有不少读者跟我反馈,能不能写图解操作系统? 既然那么多读者想看,我最近就在疯狂的复习操作系统的知识。 操作系统确实是比较难啃的一门课,至少我认为比计算机网络难太多了,但它...

敖丙
07/02
15
0
拉勾网拉你上勾

预览 需求简介 拉勾网是一个互联网行业的一个招聘网站,上面有许多职位,于是乎,小编想提取指定职位的基本信息(职位名,薪水,工作经验,工作地点,教育背景),然后插入 MongoDB 数据库,...

木下瞳
2019/04/17
20
0
我是一个线程(第一人称)

来源 | 转自 码农翻身 作者 | 刘欣 全文总共 | 4600 字 预计阅读时间 | 12 分钟 第一回 初生牛犊 我是一个线程,我一出生就被编了个号:0x3704,然后被领到一个昏暗的屋子里,在这里我发现了...

geniusian
2019/11/04
18
0
SkyWalking 权限认证

版本:7.0.0 描述 为了数据传输安全,确保网络连接是安全的。采用 Token 认证确保采集的应用数据是被信任的。 当前版本,仅支持简单的字符串 Token 配置 代理端配置文件agent.config设置 # ...

zm123321
今天
17
0
是否允许实体正文进行HTTP DELETE请求? - Is an entity body allowed for an HTTP DELETE request?

问题: When issuing an HTTP DELETE request, the request URI should completely identify the resource to delete. 发出HTTP DELETE请求时,请求URI应该完全标识要删除的资源。 However,......

javail
昨天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部