《图解设计模式》笔记(二)交给子类

三、Template Method模式:将具体处理交给子类

示例程序类图

在这里插入图片描述

public static void main(String[] args) {// 生成一个持有'H'的CharDisplay类的实例AbstractDisplay d1 = new CharDisplay('H');// 生成一个持有"Hello, world."的StringDisplay类的实例AbstractDisplay d2 = new StringDisplay("Hello, world.");// 生成一个持有"你好,世界。"的StringDisplay类的实例AbstractDisplay d3 = new StringDisplay("你好,世界。");// 由于d1、d2和d3都是AbstractDisplay类的子类,可以调用继承的display方法,实际的程序行为取决于CharDisplay类和StringDisplay类的具体实现d1.display();d2.display();d3.display();
}

角色

在这里插入图片描述

  • AbstractClass(抽象类)

    不仅负责实现模板方法,还负责声明在模板方法中所使用到的抽象方法。

    这些抽象方法由子类ConcreteClass角色负责实现。

    在示例程序中,由AbstractDisplay类扮演此角色。

  • ConcreteClass(具体类)

    该角色负责具体实现AbstractClass角色中定义的抽象方法。这里实现的方法将会在AbstractClass角色的模板方法中被调用。

    在示例程序中,由CharDisplay类和stringDisplay类扮演此角色。

扩展思路的要点

可以使逻辑处理通用化

本模式的好处:在父类的模板方法中编写了算法,无需在每个子类中再编写算法。若模板方法中发现Bug,只需修改模板方法即可。

假设没使用Template Method模式,而是复制粘贴编写了多个ConcreteClass角色,会出现ConcreteClassl、ConcreteClass2、ConcreteClass3等很多相似的类。其中一个有bug,其他类似的都得跟着再改一遍。

父类与子类之间的协作

本模式中,父类和子类是紧密联系、共同工作的。

因此,在子类中实现父类中声明的抽象方法时,必须要理解这些抽象方法被调用的时机。若看不到父类的源代码,很难编写出子类。

父类与子类的一致性

在示例程序中,不论是CharDisplay的实例还是stringDisplay的实例,都是先保存在AbstractDisplay类型的变量中,然后再来调用display方法的。

使用父类类型的变量保存子类实例的优点是:即使没有用instanceof等指定子类的种类,程序也能正常工作。

无论在父类类型的变量中保存哪个子类的实例,程序都可以正常工作,这种原则称为里氏替换原则(The Liskov Substitution Principle,LSP)。当然,LSP并非仅限于Template Method模式,它是通用的继承原则。

相关的设计模式

Factory Method模式(第4章)

Factory Method 模式是将Template Method 模式用于生成实例的一个典型例子。

Strategy模式(第10章)

在Template Method模式中,可以使用继承改变程序的行为。这是因为Template Method模式在父类中定义程序行为的框架,在子类中决定具体的处理。

与此相对的是Strategy模式,它可以使用委托改变程序的行为。

与Template Method模式中改变部分程序行为不同的是,Strategy模式用于替换整个算法。

四、Factory Method模式:将实例的生成交给子类

示例程序类图

在这里插入图片描述

Factory.java中的create方法如下,另外两个方法都是abstract

public final Product create(String owner) {Product p = createProduct(owner);registerProduct(p);return p;
}

测试

public static void main(String[] args) {Factory factory = new IDCardFactory();Product card1 = factory.create("小明");Product card2 = factory.create("小红");Product card3 = factory.create("小刚");card1.use();card2.use();card3.use();
}

角色

父类(框架)这一方的Creator角色和Product角色的关系,与子类(具体加工)这一方的ConcreteCreator角色和ConcreteProduct角色的关系,是平行的。

在这里插入图片描述

  • Product(产品)

    属于框架这一方,是一个抽象类。

    它定义了在Factory Method模式中生成的那些实例所持有的接口(API),但具体的处理则由子类ConcreteProduct角色决定。

    在示例程序中,由Product类扮演此角色。

  • Creator(创建者)

    属于框架这一方,是负责生成Product角色的抽象类,但具体的处理则由子类ConcreteCreator角色决定。

    在示例程序中,由Factory类扮演此角色。

    Creator角色对于实际负责生成实例的ConcreteCreator角色一无所知,它只知道:调用Product角色和生成实例的方法(图中的factoryMethod方法),就可以生成Product的实例。

    在示例程序中,createProduct方法是用于生成实例的方法。生成实例不是用new关键字而是调用生成实例的专用方法,这样可以防止父类与其他具体类耦合。

  • ConcreteProduct(具体的产品)

    属于具体加工这一方,它决定了具体的产品。

    在示例程序中,由IDCard类扮演此角色。

  • ConcreteCreator(具体的创建者)

    属于具体加工这一方,它负责生成具体的产品。

    在示例程序中,由IDCardFactory类扮演此角色。

扩展思路的要点

框架与具体加工

这里,让我们用相同的框架创建出其他的“产品”和“工厂”。

例如,我们这次要创建表示电视机的类Televison和表示电视机工厂的类TelevisonFactory。

这时,我们只需要引入(import)framework包就可以编写televison包。

请注意,根本没有必要修改framework包中的任何内容,就可以创建出其他的“产品”和“工厂”

请回忆一下,在framework包中我们并没有引入idcard包。在Product类和Factory类中,并没有出现IDCard和IDCardFactory等具体类的名字。

因此,使用已有的框架生成全新的类时,也完全不需要对framework进行修改,即不需要“将televison包引入到框架中”。

关于这一点,我们称作是“framework包不依赖于idcard包”。

生成实例——方法的三种实现方式

在示例程序中,Factory类的createProduct方法是抽象方法,也就是说需要在子类中实现该方法。

createProduct方法的实现方式一般有以下3种。

1.指定其为抽象方法

一旦将createProduct指定为抽象方法后,子类就必须实现该方法,否则编译错误。这也是示例程序所采用的方式。

public abstract Product createProduct(String name);

2.为其实现默认处理

实现默认处理后,如果子类没有实现该方法,将进行默认处理。

不过,这时是使用new关键字创建出实例的,因此不能将Product类定义为抽象类。

public Product createProduct(String name) {return new Product(name);
}

3.在其中抛出异常

createProduct方法的默认处理为抛出异常,这样如果未在子类中实现该方法,程序就会在运行时出错(报错,告知开发人员没有实现createProduct方法)。

使用模式与开发人员之间的沟通

建议在程序注释中和开发文档中记录所使用的设计模式的名称和意图,以免被其他开发同事瞎改。

相关的设计模式

Template Method 模式(第3章)

Factory Method模式是Template Method的典型应用。在示例程序中,create方法就是模板方法。

Singleton模式(第5章)

在多数情况下我们都可以将Singleton模式用于扮演Creator角色(或是ConcreteCreator角色)
的类。这是因为在程序中没有必要存在多个Creator角色(或是ConcreteCreator角色)的实例。不
过在示例程序中,我们并没有使用Singleton模式。

Composite模式(第11章)

有时可以将Composite模式用于Product 角色(或是ConcreteProduct 角色)。

Iterator模式(第1章)适应设计模式-Iterator模式

有时,在Iterator模式中使用iterator方法生成Iterator的实例时会使用Factory Method模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/695303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ Linux多线程

1. C语言线程安全问题 1.1 线程安全问题 #include <stdio.h> #include <tinycthread.h> #include <io_utils.h>int count 0; int Counter(void*arg) {for(int i 0;i<100000;i){count;/** int temp count;* counttemp1;* return temp;* */}return 0; …

大模型训练流程(三)奖励模型

为什么需要奖励模型 因为指令微调后的模型输出可能不符合人类偏好&#xff0c;所以需要利用强化学习优化模型&#xff0c;而奖励模型是强化学习的关键一步&#xff0c;所以需要训练奖励模型。 1.模型输出可能不符合人类偏好 上一篇讲的SFT只是将预训练模型中的知识给引导出来…

Vue+SpringBoot打造大学兼职教师管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 学生教师管理3.3 课程管理模块3.4 授课管理模块3.5 课程考勤模块3.6 课程评价模块3.7 课程成绩模块3.8 可视化图表 四、免责说明 一、摘要 1.1 项目介绍 大学兼职教师管理系统&#xff0c;旨…

基于 QUIC 协议的 HTTP/3 正式发布!

近期&#xff0c;超文本传输协议新版本 HTTP/3 RFC 文档&#xff0c;已由互联网工程任务组&#xff08;IETF&#xff09;对外发布。HTTP/3 全称为 HTTP-over-QUIC&#xff0c;指在 QUIC&#xff08;Quick UDP Internet Connections, 快速 UDP 互联网连接&#xff09;上映射 HTT…

基于Java+小程序点餐系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

如何使用CanaryTokenScanner识别Microsoft Office文档中的Canary令牌和可疑URL

关于CanaryTokenScanner CanaryTokenScanner是一款功能强大的Canary令牌和可疑URL检测工具&#xff0c;该工具基于纯Python开发&#xff0c;可以帮助广大研究人员快速检测Microsoft Office和Zip压缩文件中的Canary令牌和可疑URL。 在网络安全领域中&#xff0c;保持警惕和主动…

Leo赠书活动-17期 《基础软件之路:企业级实践及开源之路》

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

【网站项目】167校园失物招领小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Day10_面向对象-抽象类-接口-课后练习-参考答案

文章目录 代码编程题第1题第2题第3题 代码编程题 第1题 知识点&#xff1a;抽象类语法点&#xff1a;继承&#xff0c;抽象类按步骤编写代码&#xff0c;效果如图所示&#xff1a; 编写步骤&#xff1a; 定义抽象类A&#xff0c;抽象类B继承A&#xff0c;普通类C继承BA类中&…

Java,SpringBoot项目中,Postman的测试方法。

目录 展示查询搜索 根据id展示数据 根据id删除数据 根据id更新数据 添加数据 展示查询搜索 // 根据姓名分页查询用户GetMapping("/getUsersByName")public IPage<User> getUsersByName(RequestParam(defaultValue "1") Long current,RequestPar…

(っ•̀ω•́)っ 如何在PPT中为文本框添加滚动条

本人在写技术分享的PPT时&#xff0c;遇到问题&#xff1a;有一大篇的代码&#xff0c;如何在一张PPT页面上显示&#xff1f;急需带有滚动条的文本框&#xff01;百度了不少&#xff0c;自己也来总结一篇&#xff0c;如下&#xff1a; 1、找到【文件】-【选项】 2、【自定义功…

《深入浅出 Spring Boot 3.x》预计3月份发版

各位&#xff0c;目前本来新书《深入浅出 Spring Boot 3.x》已经到了最后编辑排版阶段&#xff0c;即将在3月份发布。 目录&#xff1a; 现在把目录截取给大家&#xff1a; 主要内容&#xff1a; 本书内容安排如下。 ● 第 1 章和第 2 章讲解 Spring Boot 和传统 Spri…

万界星空科技MES系统,实现数字化智能工厂

万界星空科技帮助制造型企业解决生产过程中遇到的生产过程不透明&#xff0c;防错成本高&#xff0c;追溯困难&#xff0c;品质不可控&#xff0c;人工效率低下&#xff0c;库存积压&#xff0c;交期延误等问题&#xff0c;从而达到“降本增效”的目标。打通各个信息孤岛&#…

深入解析SDRAM:从工作原理到实际应用

深入解析SDRAM&#xff1a;从工作原理到实际应用 在众多内存技术中&#xff0c;同步动态随机访问存储器&#xff08;SDRAM&#xff09;因其出色的性能和广泛的应用而备受关注。本文将从SDRAM的工作原理入手&#xff0c;探讨其性能优化策略和在现代电子设备中的应用。 SDRAM工作…

Meta 发布 MMCSG (多模态智能眼镜对话数据集)

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Redis突现拒绝连接问题处理总结

一、问题回顾 项目突然报异常 [INFO] 2024-02-20 10:09:43.116 i.l.core.protocol.ConnectionWatchdog [171]: Reconnecting, last destination was 192.168.0.231:6379 [WARN] 2024-02-20 10:09:43.120 i.l.core.protocol.ConnectionWatchdog [151]: Cannot reconnect…

【LeetCode】树的BFS(层序遍历)精选6题

目录 1. N 叉树的层序遍历&#xff08;中等&#xff09; 2. 二叉树的锯齿形层序遍历&#xff08;中等&#xff09; 3. 二叉树的最大宽度&#xff08;中等&#xff09; 4. 在每个树行中找最大值&#xff08;中等&#xff09; 5. 找树左下角的值&#xff08;中等&#xff09…

win10编译openjdk源码

上篇文章作者在ubuntu系统上实践完成openjdk源码的编译&#xff0c;但是平常使用更多的是window系统&#xff0c;ubuntu上编译出来JDK无法再windows上使用。所以作者又花费了很长时间在windows系统上完成openjdk源码的编译&#xff0c;陆续花费一个月的时间终于完成了编译。 本…

【设计模式】使用适配器模式做补偿设计

文章目录 1.概述2.两种适配器模式2.1.类适配器2.2.对象适配器 3.总结 1.概述 适配器模式是一种结构型设计模式&#xff0c;它提供了一个中间层&#xff0c;通过这个中间层&#xff0c;客户端可以使用统一的接口与具有不同接口的类进行交互&#xff0c;也就是说&#xff0c;将一…

人工智能深度学习

目录 人工智能 深度学习 机器学习 神经网络 机器学习的范围 模式识别 数据挖掘 统计学习 计算机视觉 语音识别 自然语言处理 机器学习的方法 回归算法 神经网络 SVM&#xff08;支持向量机&#xff09; 聚类算法 降维算法 推荐算法 其他 机器学习的分类 机器…