墨风如雪博客

  • 源码小店
  • 导航站
  • 登录
  • java
  • 资源分享
让AI使用变得如此简单
  1. 首页
  2. java
  3. 设计模式
  4. 正文

设计模式:模板方法模式

2023年 5月 12日 148点热度 0人点赞 0条评论

模板方法设计模式介绍

模板方法设计模式是一种行为型设计模式,它定义了一个算法的骨架,将算法中一些步骤的具体实现延迟到子类中。模板方法模式使得子类可以在不改变算法骨架的情况下重新定义算法中某些步骤的具体实现。

模板方法模式通常包含以下角色:

  1. 抽象类(Abstract Class):定义了一个模板方法,该方法中包含了算法的骨架和一些抽象方法,用于延迟到子类中实现。

  2. 具体类(Concrete Class):实现了抽象类中的抽象方法,并提供算法的具体实现。

下面是一个简单的模板方法模式的示例:

// 抽象类
public abstract class AbstractClass {
    // 模板方法
    public final void templateMethod() {
        // 调用基本方法
        operation1();
        // 调用钩子方法
        if (hookMethod()) {
            operation2();
        }
        // 调用基本方法
        operation3();
    }

    // 基本方法1
    public abstract void operation1();

    // 基本方法3
    public abstract void operation3();

    // 钩子方法
    public boolean hookMethod() {
        return true;
    }

    // 抽象方法2,由子类实现
    public abstract void operation2();
}

// 具体类
public class ConcreteClass extends AbstractClass {
    public void operation1() {
        System.out.println("ConcreteClass: operation1");
    }

    public void operation2() {
        System.out.println("ConcreteClass: operation2");
    }

    public void operation3() {
        System.out.println("ConcreteClass: operation3");
    }
}

// 测试类
public class TemplateMethodPatternDemo {
    public static void main(String[] args) {
        AbstractClass abstractClass = new ConcreteClass();
        abstractClass.templateMethod();
    }
}

在这个例子中,我们定义了一个抽象类AbstractClass,其中包含了一个模板方法templateMethod()和一些基本方法和钩子方法,用于延迟到子类中实现。然后,我们创建了一个具体类ConcreteClass,继承自AbstractClass,并实现了其中的抽象方法。最后,在客户端应用程序中,我们创建了一个AbstractClass对象,并通过它的模板方法templateMethod()调用算法。

通过模板方法模式,我们可以将算法的骨架与具体的实现分离开来,并允许子类重新定义算法中的某些步骤,从而提高代码的复用性和可维护性。

spring当中的使用

在Spring框架中,模板方法模式被广泛应用,其中最常见的应用是JdbcTemplate类。JdbcTemplate类是Spring框架提供的一个数据库访问工具,它封装了JDBC API,提供了一种更加简单和易用的方式来访问数据库。JdbcTemplate使用模板方法模式实现了数据库操作的统一流程,从而方便了开发人员进行数据库访问。

下面是一个使用Spring的JdbcTemplate类的例子:

// 定义一个 DAO 接口
public interface UserDao {
    void addUser(User user);
    void updateUser(User user);
    void deleteUserById(Long id);
    User getUserById(Long id);
}

// 实现 DAO 接口
@Repository
public class UserDaoImpl implements UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void addUser(User user) {
        String sql = "INSERT INTO users(id, name, age) VALUES(?, ?, ?)";
        jdbcTemplate.update(sql, user.getId(), user.getName(), user.getAge());
    }

    public void updateUser(User user) {
        String sql = "UPDATE users SET name = ?, age = ? WHERE id = ?";
        jdbcTemplate.update(sql, user.getName(), user.getAge(), user.getId());
    }

    public void deleteUserById(Long id) {
        String sql = "DELETE FROM users WHERE id = ?";
        jdbcTemplate.update(sql, id);
    }

    public User getUserById(Long id) {
        String sql = "SELECT * FROM users WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
    }
}

// 定义一个行映射器
public class UserRowMapper implements RowMapper<User> {
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {
        User user = new User();
        user.setId(rs.getLong("id"));
        user.setName(rs.getString("name"));
        user.setAge(rs.getInt("age"));
        return user;
    }
}

// 使用 DAO
public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserDao userDao = context.getBean(UserDao.class);

        // 添加用户
        User user1 = new User(1L, "Alice", 20);
        userDao.addUser(user1);

        // 更新用户
        User user2 = new User(1L, "Bob", 25);
        userDao.updateUser(user2);

        // 获取用户
        User user3 = userDao.getUserById(1L);
        System.out.println(user3);

        // 删除用户
        userDao.deleteUserById(1L);
    }
}

// 定义配置类
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // 配置数据源
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource());
    }

    @Bean
    public UserDao userDao() {
        return new UserDaoImpl();
    }
}

在这个例子中,我们定义了一个DAO接口UserDao和其实现类UserDaoImpl,其中使用了Spring的JdbcTemplate类来访问数据库。JdbcTemplate类使用模板方法模式实现了数据库操作的统一流程,从而方便了开发人员进行数据库访问。通过在配置类中注入JdbcTemplate和DataSource对象,我们可以在DAO实现类中直接使用JdbcTemplate对象来执行数据库操作。

Spring的JdbcTemplate类是模板方法模式的一个典型应用,它将数据库操作的过程抽象成一个模板方法,并将一些基本方法和钩子方法延迟到子类中实现。通过使用JdbcTemplate类,我们可以方便地进行数据库访问,同时避免了一些重复的代码和错误处理逻辑。

过度设计的后果

过度使用模板方法设计模式可能会引发以下问题:

  1. 破坏封装性:模板方法设计模式需要将算法的骨架封装在抽象类中,而将具体的实现延迟到子类中实现。如果过度使用模板方法设计模式,可能会导致抽象类中的代码变得过于复杂,从而破坏了封装性,使得系统难以理解和维护。

  2. 限制扩展性:模板方法设计模式将算法的骨架固定在抽象类中,而将具体的实现延迟到子类中实现。如果需要对算法进行扩展,可能需要修改抽象类的代码,从而影响到所有的子类。这样的设计可能会限制系统的扩展性,使得系统难以应对变化和需求的变化。

  3. 降低代码的灵活性:模板方法设计模式需要将算法的骨架固定在抽象类中,而将具体的实现延迟到子类中实现。这种设计可能会使得代码的灵活性降低,并且难以应对不同的算法和需求的变化。

  4. 多层继承问题:如果过度使用模板方法设计模式,可能会导致多层继承的问题。由于子类需要继承抽象类中的方法,而抽象类又继承自其他的抽象类,这可能会导致类层次结构变得过于复杂,从而影响系统的可维护性和可扩展性。

因此,在使用模板方法设计模式时,需要谨慎使用,并避免过度使用。需要根据具体的场景和需求进行设计和选择,保证设计的可维护性、可扩展性和灵活性。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: java 介绍 教程 模板方法设计模式 设计模式
最后更新:2023年 5月 10日

墨风如雪

一个热爱生活,热爱分享的程序员

打赏 点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

墨风如雪

一个热爱生活,热爱分享的程序员

最新 热点 随机
最新 热点 随机
阿里WebAgent开源:引领自主搜索新纪元 重磅炸弹!字节跳动开源BAGEL:70亿参数,统一多模态理解与生成,AI“全能王”诞生记! 小米MiMo-VL:7B参数,怎么就成了多模态界的“越级打怪王”? 炸裂!DeepSeek 8B 量化版降临:告别显存焦虑,你的 3080 Ti 也能玩转顶级大模型了! 美团炸场AI圈:点外卖点出个软件?用「对话式编程」重塑生产力! 当你的证件照学会了眨眼微笑:腾讯混元 HunyuanPortrait 开源,让数字肖像「活过来」!
重塑AI推理格局?微软Phi-4模型震撼发布:轻量化性能炸裂炸裂!微软这门免费AI Agent新手课,GitHub近2万星,简直是宝藏!ComfyUI“打通任督二脉”:直接调用Veo2、GPT-4o等65大模型!一键串联你的AI工作流AI圈炸锅了!Mistral Medium 3:性能 SOTA,成本打骨折,企业玩家的新宠?字节终于开源“扣子”同款引擎了!FlowGram:AI 时代的可视化工作流利器告别“微信黑箱”!Chatlog:让你的聊天记录也能拥有“AI大脑”!
利用Open Web UI实现DeepSeek R1完全体+联网搜索功能指南 browser-use: 让你的代码像人一样“上网冲浪”——API驱动的浏览器自动化利器 重磅!小米刚刚发布了4款AI模型:7B小模型逆袭,硬刚GPT-4o! JAVA当中继承知识点,理解应用和优化 常见的十大排序算法解析 告别工具切换噩梦!阿里巴巴通义万相 Wan2.1-VACE:一个模型,通吃视频生成与编辑!
标签聚合
AI 算法 deepseek 设计模式 动态规划 教程 spring java

COPYRIGHT © 2023 墨风如雪博客. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

免责声明 - 隐私政策