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

三、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模式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS应用开发】三方库(二十)

三方库的基本使用 一、如何获取三方库 目前提供了两种途径获取开源三方库: 通过访问Gitee网站开源社区获取 在Gitee中,搜索OpenHarmony-TPC仓库,在tpc_resource中对三方库进行了资源汇总,可以供开发者参考。 通过OpenHarmony三…

数字世界的探索者:计算机相关专业电影精选推荐

目录 推荐计算机专业必看的几部电影 《黑客帝国》 《社交网络》 《乔布斯传》 《心灵捕手》 《源代码》 《盗梦空间》 《头号玩家》 《我是谁:没有绝对安全的系统》 《战争游戏》(WarGames) 《模仿游戏》(The Imitation Game) 《硅谷》(Silicon Valley) …

SpringBoot+WebSocket实现即时通讯(四)

前言 紧接着上文《SpringBootWebSocket实现即时通讯(三)》 本博客姊妹篇 SpringBootWebSocket实现即时通讯(一)SpringBootWebSocket实现即时通讯(二)SpringBootWebSocket实现即时通讯(三&…

如何在Shopee 上选择热销商品?shopee应该在哪选品

在如今激烈竞争的电商市场中,如何通过精准的选品策略提升在Shopee平台上的销售业绩成为卖家们关注的焦点。Shopee作为一个蓬勃发展的电商平台,提供了多种资源和工具来帮助卖家做出明智的选品决策。通过深入了解这些渠道和策略,卖家们可以更好…

第2.4章 StarRocks表设计——分区分桶与副本数

目录 一、数据分布 1.1 概述 1.2 数据分布方式 1.2.1 Round-Robin 1.2.2 Range 1.2.3 List 1.2.4 Hash 1.3 StarRocks的数据分布方式 1.3.1 不分区 Hash分桶 1.3.2 Range分区Hash分桶 三、分区 3.1 分区概述 3.2 创建分区 3.2.1 手动创建分区 3.2.2 批量创建分区…

微服务篇之负载均衡

一、Ribbon负载均衡流程 二、Ribbon负载均衡策略 1. RoundRobinRule:简单轮询服务列表来选择服务器。 2. WeightedResponseTimeRule:按照权重来选择服务器,响应时间越长,权重越小。 3. RandomRule:随机选择一个可用的服…

Java 那些诗一般的 数据类型 (1)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…

如何实现一个K8S DevicePlugin?

什么是device plugin k8s允许限制容器对资源的使用,比如CPU和内存,并以此作为调度的依据。 当其他非官方支持的设备类型需要参与到k8s的工作流程中时,就需要实现一个device plugin。 Kubernetes提供了一个设备插件框架,你可以用…

一文读懂函数式接口、Lambda表达式、Stream

文章目录 前言版本函数式接口定义特点使用 Lambda表达式主要场景用法无参写法有参写法 Lambda 表达式的基础:函数式接口 类型推断自定义函数接口使用 Lambda 表达式底层实现JDK7JDK8 this 的含义JDK7JDK8 Stream特点操作Stream 流创建中间操作和终端操中间操作无状…

vue.js el-tooltip根据文字长度控制是否提示toolTip

一、需求&#xff1a;如何判断当前文本文字是否超出文本长度&#xff0c;是否需要出现提示toolTip。效果图如下&#xff1a; 二、实现&#xff1a; 1、表格字段鼠标放置el-popover出现 “引用主题” 的具体内容&#xff1b; <!-- 表格字段&#xff1a;引用主题 --> <…

006 矢量数据属性表的使用和关联

1 空间属性关系 1.1 数据导入和图层组合 读取数据 除了使用关键项的连接之外&#xff0c;还有一种根据属性组合中的空间位置关系进行组合的方法。 在本节中&#xff0c;我们将介绍一种方法&#xff0c;用于将空间关系中的多边形数据属性与任意点数据属性相结合。 我们使用的是…

文件上传漏洞--Upload-labs--Pass11--(GET)00绕过

一、环境准备&#xff1a; php版本&#xff1a;推荐 php5.2.17&#xff08;官方推荐版本&#xff09;。小于php5.3.4也可以&#xff0c;但是要在 php.ini 配置文件中手动将 magic_quotes_gpc 的状态改为 Off。 magic_quotes_gpc的作用是对 get请求、post请求、cookie...传入的…

DIcom调试Planar configuration

最近和CBCT组同事调dicom图像 这边得图像模块老不兼容对方得dicom文件。 vtk兼容&#xff0c;自己写得原生解析不兼容。 给对方调好了格式&#xff0c;下次生成文件还会有错。 简单记录下&#xff0c;日后备查。 今天对方又加了 个字段&#xff1a;Planar configuration 查…

【开源】JAVA+Vue.js实现高校学生管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生管理模块2.2 学院课程模块2.3 学生选课模块2.4 成绩管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学生表3.2.2 学院课程表3.2.3 学生选课表3.2.4 学生成绩表 四、系统展示五、核心代码5.1 查询课程5.2 新…

FPS游戏漫谈弱网环境时延优化

游戏在弱网情况下会变得体验很差&#xff0c;玩家的直观感受就是我的操作怎么没有反应&#xff0c;整个游戏世界都是一卡一顿的。这个就是因为网络问题导致了游戏体验变差。 那什么是弱网环境&#xff1f;弱网环境就是指网络不好的环境&#xff0c;尤其是移动网络下&#xff0…

Java毕业设计-基于springboot的人才招聘管理系统-第68期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于springboot的人才招聘管理系统&#xff1a;前端jquery、easyui&#xff0c;后端 maven、springmvc、spring、jpa、hibernate&#xff0c;集成职位浏览、我的简历、投…

web前端宝藏题库,适用于0-3年前端工程师...

前些天意外认识了一个前端大佬&#xff0c;某大厂在职&#xff0c;我怕打扰就没敢多聊&#xff0c;没想到大佬挺平易近人&#xff0c;很亲切的给我出谋划策&#xff0c;还给了我一套面试题&#xff0c;难度不是很高&#xff0c;但是胜在全面十分契合我现在的状况&#xff0c;所…

在VsCode中通过Cookie登录LeetCode

在vscode中配置好leetcode之后&#xff0c;一般最常用的就是通过cookie登录leetcode ; 首先点击sign in &#xff0c; 然后选择最下面的 &#xff0c; LeetCode Cookie ! 然后输入username(也就是你的lc用户名) 或者 你leetcode绑定的邮箱 ; 输入完成之后 ; 就是要你输入你的l…

UE5 C++ 创建可缩放的相机

一.要将相机设置在Pawn类里 1.在MyPawn头文件里&#xff0c;加上摇臂和相机组件 #include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h" 2.在Pawm里声明SceneComponet&#xff0c;SpringArmComponent,CameraComponent组件…

6.【架构师成长之路】职场新人:维护一张能力图谱

文章目录 导言一、能力图谱就是技能体系1、时刻提醒你&#xff0c;你有一个目标2、你可以知道靠近目标的具体方式3、你会变得更加自信 二、周期性review自己的能力图谱1、review能力项进度2、review能力项完整度3、固定周期review 本文总结说明 导言 上两篇文章我们讲了&#…