Design Patterns Lecture 4.

Slides:



Advertisements
Similar presentations
1 曾老師、各位同學大家好 ! 首先自我介紹 ; 個人聯合大學電機系 畢業,服完兩年兵役後, 75 年開始就 業 ; 四年內換了幾個工作, 79 年創立貿 特科技, 90 年、 91 年分別於大陸寧波 與昆山設立特一電子與柏特電子,經 歷 20 年的工作磨鍊,今天事業上算是 穩定、成熟 ! 承蒙曾老師看重,利用一.
Advertisements

中正國中 特教組長 粘玉芳 校內分機 : /02/21. 下列條件擇一: 一、身心障礙手冊 二、特殊教育學生鑑定及就學輔導會證明.
如何科学认识风水 主讲嘉宾孙百川 揭开神秘的面纱 揭开神秘的面纱 破除迷信的枷锁 破除迷信的枷锁 还易经本来面目 还易经本来面目 学易用易不迷易 学易用易不迷易.
魏晉南北朝的胡漢融和概況. 北朝的漢胡融和 1) 北朝漢胡 融和的概 況 2) 北魏孝文 帝推行的 漢化措施 及影響 北邊民族徙居中原,由 來已久。自曹魏招用胡 兵始,沿邊胡族內徙日 繁。不少胡族君主更傾 心嚮慕漢族文化,大力 促成胡漢的融和。北魏 推行的漢化措施,影響 尤為深遠。
面向对象与设计模式 RD 常见编程范式介绍  并行编程 - Process-orientedProcess-oriented  组件编程 - Component-basedComponent-based  事件驱动 - Service-oriented,Time-drivenService-orientedTime-driven.
漫谈架构设计. 课程目的  最难的课程  架构师的成长,有没有捷径?  架构师能不能成体系的培养?  寻找我的直觉的来源 : 这些自觉不连续,不成体系,我想整理 (但在我自己这里是整体性的,对同样的问 题,我总是能得到几乎一样的答案)
示範課 -- 作文立意. 重溫作文構思課  構思嘗試深化  多角度思考  宜先剖析題目, 運用聯想, 循序漸進擴大範圍, 然後歸納材料, 定訂主題  同學的作品, 反映部分能夠掌握, 主線清晰, 層 層深入, 舉例恰當  但有部分同學只有枝葉, 欠缺主線, 更無中心思 想, 反映立意不足.
模仿貓 記敘文 ( 童話 ) 作者: 海倫、波頓 課文朗讀課文朗讀、模仿大賽 作者 美國女畫家,她用藝術家的嚴 肅態度和精神,幫兒童讀繪畫 插圖,並得過許多次獎。她的 作品藝術價值高,有雨本成為 美國美術協會兒童讀物展覽的 入選作品。她常常自寫自畫, 文筆很不錯。
有教無類 因材施教 適性揚才 多元進路 優質銜接
数据库原理及应用(ORACLE)实用教程
第16章 代理模式 Website:
軟體工程 -物件導向程式設計與UML系統分析實作
性教育教學模組設計 主題:身體自主權 台中市忠明國小 巫偉鈴.
整体销售方案 中山市美好物业代理有限公司
关于市场营销的分析 ——以九阳豆浆机为例 品牌经营——让每一个家庭都拥有一台九阳豆浆机 营销管理——采取文化、概念、网络等营销组合
国学传统与企业文化建设 刘大洋 博士.
第22章 Flex应用程序开发 在本章以前的章节中,花了很大的精力来讲解组件、数据等内容,毕竟大部分的开发者使用Flex都是受因为其强大的表示层功能吸引。本章在前面的基础上,进一步介绍Flex应用程序的开发。与前面的章节相比,本章将从整体上把握如何开发Flex应用,侧重于设计模式问题、安全、性能优化等。
臺中市頭家國小 生理衛生講座 青春期的奧秘 ‧說到青春期,你會想到? ‧班級表現最好的,有獎徵答有優先權。 葉孟娟老師、黃文玲老師.
基于SSH的web开发 AND 企业级WEB应用开发新技术
模块二顶级销售人员是如何造就的.
美学概论 主讲教师 孙建章 沈阳电大文法系.
大家都来关注国家安全 南京市江宁中学 傅德柱.
Java Programming Hygiene - for DIDC
MVC Servlet与MVC设计模式.
第十一章:思路与谋篇 教学内容: 1、思路及有关概念; 2、谋篇(结构)的原则; 3、谋篇的方法(层次段落安排, 过度与照应,开头与结尾).
1. 民主社會裡,公民的參與有其重要性,而透過政治參與無法達成下列哪一項目的?
J2EE Struts 和Spring 的区别.
授课教师简历 刘付才,男,中学高级教师,亳州一中南校体 育教研组长,全国体育优质课一等奖获得者,华佗 五禽戏第五十八代传承人;长期从事五禽戏教学和 研究工作,参与创编了国家级课题“校园五禽戏”; 2014年全国学生运动会展示中获得优秀表演奖; 2015年指导的五禽戏传人进行的五禽戏教学获得全 国一等奖,编著的《华佗五禽戏之简易健身操》即.
英國軍事理論家-富勒 黃詩妤 王業嘉 指導教官 周家榮.
洪涝灾害重点传染病的预防 江苏省疾病预防控制中心 汪华.
第七章 数据库管理系统.
9理直氣和—記敘文 說理如強硬,則不易被接受,以故事方式來激發反思,是比較不傷和氣而且高明的技巧。
俄语字母的发音体系 阅读规则.
小 桔 灯 市场赢利能力与战略 主讲:杨贤耀.
氣候變遷對南台灣降雨造成之影響 研究背景 結果與討論 研究方法 結論 朱振豪1 、彭康豪1 、莊煌甲1 、邱俊彥2,* 研究目的
不動產市場 分析與預測 第四章 不動產市場分析與研究.
践行新时期广东精神 推进广东公路文化繁荣与发展 ——关于广东省公路文化建设与实践的思考
第九章 组织中的职权配置 第一节 权力、职权与指挥链 第二节 授权 第三节 组织成员的活性化 第四节 分权和集权
第八章 分析與設計階段 – 物件導向設計(OOD)
Object Oriented Analysis and Design
潘爱民 软件设计模式(二) 潘爱民
Design Pattern (2) 设计模式(2) Institute of Computer Software 2018/9/21
.NET 提升教育 CYQ.Data 精通课程 By 路过秋天
Design Pattern (3) 设计模式(3) Institute of Computer Software 2018/11/8
数据库操作示例 import java.sql.*; //导入java.sql包 public class JDBCDemo {
Mobile & Embedded DevCon 2005 朱敏博士 微软有限公司
物件導向系統分析與設計與UML.
Design Pattern (1) 设计模式(1) Institute of Computer Software 2018/11/23
创建型设计模式.
Swing高级组件 主讲:赖国荣 QQ:
周宇 南京航空航天大学 软件设计模式与体系结构 周宇 南京航空航天大学
软件建模训练(6-2) 设计模式 张静 南京理工大学计算机科学与工程学院.
职责链模式.
集合框架和泛型(一).
两种不同类别的软件: 功能预定义软件;用户驱动的软件。他们对软件工程方法有不同的需求
第11章 系统结构与包模型模型.
简单工厂模式.
文本讀寫策略vs 繪本多元寫作 國立新竹教育大學附設實驗國民小學 葉惠貞.
电子商务 王素凤
管理信息系统 第九章 面向对象的系统开发方法.
第三章 世界文明的蛻變與互動 第一節 歐洲社會的蛻變 第二節 世界文明的交匯 第三節 亞洲大帝國的發展 1.
中国农业科学院博士后学术论坛 博士后基金申请的经验及体会 中国农业科学院生物技术研究所 秦 华 博士
第二章 Java基本语法 讲师:复凡.
厉害了,我的国! 15会计2班团支部 2018年4月20日.
1.4数据库管理系统 数据库管理系统是数据库系统的核心,是为数据库的建立,维护,使用而建立的系统软件,建立在操作系统基础之上,位于操作系统与用户之间的数据管理软件,负责对数据库进行统一管理与控制.
----以《西北民族音乐学术资源数据库》为例 西安音乐学院 景 月 亲
PureMVC 孙晓申.
第21章 Spring 的MVC框架 Spring不但一个很好的集成框剪,它还提供了构建Web应用程序的全功能MVC模块。Spring 的MVC框架非常强大并不逊色于其他专业的Web框架,如Struts、WebWork。但在国内Spring MVC应用的并不是特别多,原因可能是Struts太深入人心的缘故吧。
6 集合类与泛型.
Presentation transcript:

Design Patterns Lecture 4

Types of Design Patterns Creational Structural Behavioural Abstract Factory Builder Factory Prototype Singleton Adapter Bridge Composite Decorator Façade Flyweight Proxy Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 观察者模式 意图 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 适用性 当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。 当对一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的。

Observer模式的实现 由原理不难看出Observer模式的实现关键在于 Subject和Observers间的协同工作。为了响应数据 变更,Observers需要实现接口: abstract interface Observer { public void sendNotify(数据变更); } 然后Observers将其注册到Subject,数据变换时由 其调用接口的sendNotify通知Observers刷新。显 然,Subject需要实现以下接口来接受注册。 abstract interface Subject { public void registerInterest(Observer obs); Subject要通知Observer数据变更,需要采用函数回调的方法,因此要求所有Observers都具有相同的回调函数(也即是它们有共性)。让Observers实现相同的接口,接口里面包含回调函数,问题可解。 Observers将其注册到Subject,也要求Subject有一个统一的接收注册的接口。有了该接口,一个Observer就能注册到多个Subject中。 当需要添加新的数据表现形式,只要创建实现Observers接口的类即可,同理如需要改变数据模型,也只是修改Subject接口的类实现而已。整个系统的弹性非常好,任何一部分的变更都不对其它部分造成任何影响,添加新的特性十分方便。

Observer模式与MVC MVC(Model-View-Controller)的核心思 想和Observer模式是完全类似的。数据模型 (业务逻辑)和表现逻辑相互隔离, Controller则负责与客户交互,根据请求调用M 和V的功能。 通常情况下Controller并不单独存在,而是 和M或V结合(JFC中便是如此)。但在分布式 系统中,客户端不可能直接与M或V进行交互, 此时Controller将独立出来并发挥重要作用。 访问协议、请求分发、安全认证、日志记录和 异常处理等都由其承担。 JFC是用于设计交互界面的,客户对数据的控制往往要通过界面(也是View)来完成,所以Controller常与View结合在一起。 分布式系统中,客户与M和V,或者M与V之间都是隔离的(且经常会是物理上的隔离),J2EE环境下是最典型的例子。因此需要靠Controller来与客户端打交道,根据客户的请求调用M和V。此时,Controller变成了整个系统的动力所在,缺少它系统无法运转。由于处于跟用户交互的第一线,访问协议的解释、请求分发、安全认证等重担都落到了Controller的肩上。 总体上看,Observer和MVC在本质上并没有太多的区别,只是应用范围的不同引起差异。MVC通常会用在分布式系统中,而交互式的应用程序一般使用Observer。

提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 迭代子模式 意图 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 适用性 访问一个聚合对象的内容而无需暴露它的内部表示。 支持对聚合对象的多种遍历。 为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

Iterator模式的接口定义 Iterator的接口定义大同小异,可以根据具 体的情况定制。通常情况下,接口定义如下: public interface Iterator { public Object First(); public Object Next(); public boolean hasNext(); public Object CurrentItem(); }

Iterator和Composite模式 Composite模式常用于组织树型结构数据,故 同样会面临数据遍历的问题。树型数据的遍历主要 有两种不同的算法:深度优先和广度优先。利用 Iterator,可以将具体的遍历算法屏蔽,客户端也 就不再受算法的困扰。 此外,Iterator还可用于每个节点所包含子节 点的遍历。 需要注意的是Iterator使用的是pull模型来遍历数据,也就是主动获取,这个和后面所介绍的Visitor不同,Visitor采用的是push模型。

责任链模式 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 适用性 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 可处理一个请求的对象集合应被动态指定。

Chain of Responsibility的实现 该模式的实现关键在于响应链的实现,即是 将所有request的处理类串起来形成响应链。响 应链的操作主要是添加处理类和激发处理类,用 接口表示如下: public interface Chain { public void addChain(Chain c); public void invoke(String mesg); … } 所有的处理类都实现以上接口,即可组成响应链。 要将处理类串起来(形成一个集合,即响应链),前提就是处理类要有共性(实现共同的接口或者虚类),否则无法串到一起。 处理类既然要有共性来形成响应链,自然最关键的共性就是体现响应链的操作。 结合UML类图来说明响应链的结构。 响应链有两种结构:链式和树型。其核心思想是完全一样的,仅仅是数据组织方式的区别而已。

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 备忘录模式 意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 适用性 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。 命令模式 意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。 适用性 你可用过程语言中的回调(c a l l b a c k )函数表达这种参数化机制。所谓回调函数是指函数先在某处注册,而它将在稍后某个需要的时候被调用。C o m m a n d 模式是回调机制的一个面向对象的替代品。 在不同的时刻指定、排列和执行请求。一个C o m m a n d 对象可以有一个与初始请求无关的生存期。如果一个请求的接收者可用一种与地址空间无关的方式表达,那么就可将负责该请求的命令对象传送给另一个不同的进程并在那儿实现该请求。 支持取消操作。C o m m a n d 的E x c u t e 操作可在实施操作前将状态存储起来,在取消操作时这个状态用来消除该操作的影响。C o m m a n d 接口必须添加一个U n e x e c u t e 操作,该操作取消上一次E x e c u t e 调用的效果。执行的命令被存储在一个历史列表中。可通过向后和向前遍历这一列表并分别调用U n e x e c u t e 和E x e c u t e 来实现重数不限的“取消”和“重做”。 理解的关键是将命令本身和命令的执行体分开,可以以开电脑为例,主板上有开电脑键,激发一个开电脑命令,但是这个命令不是按钮完成的,按钮只是Invoker,真正开机过程的是由主板完成的。

Command模式Vs责任链模式 Command模式和响应链都起到了隔离处理 代码和使响应端对客户端透明的作用。 Command模式简化和优化了request到处 理代码的传递,为request的扩展提供良好支持。 责任链只是将传递流程以链式或树型结构管 理起来,为处理代码的激发顺序提供了很好的灵 活性。 在已往的做法中,request到处理代码的传递需要使用大量的if或switch语句及各种判断条件。Command模式将request传递和处理代码进行了彻底的隔离,处理类中不包含任何条件判断。 request传递代码隔离出来后,往往可以借助数组、链表或散列进行简化和优化。因此随着request种类的增长,Command模式能依然保持良好的性能。 响应链实际上只是将if或switch语句转化成链式或者树型的结构管理起来,对于判断条件不作任何处理,仍然保留在处理代码中。故其对request传递没有任何的简化或优化处理,随着request种类的增长,性能瓶颈会逐渐显露,但它提供了处理代码激发顺序的灵活性,这是Command模式无法提供。 当然,这些区别都是由其应用范围所决定的。还要注意的是Command模式并不像响应链,专门为响应request而存在, Command模式还有其它的应用,在后面的举例中将可以看到。

Command模式的应用举例 Servlet是完全遵照Command模式设计的。每 个Servlet都包含两个激发函数doGet和doPost。 激活Servlet的URL或Map则在部署文件里设定。 JUnit也是以Command模式为基础的。 TestCase需要通过TestSuit以树型的结构组织起来。 这样就必须将所有TestCase设计成具有统一激活接 口的类。 采用Command模式后,request的传递和处理代码完全分离,因此可以将request的传递规则写到部署文件里面,由容器来解释执行。 由应用举例可以看出Command模式的应用范围: 1.根据不同的request执行相应理代码。 2.将处理代码以一种数据结构组织起来。

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 状态模式 意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 适用性 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。S t a t e模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 访问者模式 意图 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 适用性 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Vi s i t o r 使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Vi s i t o r 模式让每个应用仅包含需要用到的操作。 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

Visitor模式的实现 Visitor的实现主要是两个步骤: 所有被访问的对象都要实现函数 public void accept(Visitor v) { v.visit(this); //call visitor method } 遍历数据之前先创建Visitor,然后遍历的过程中调用每个类的accept函数 第一步中,如果访问的对象是不同的,那就要使其实现一个接口或继承于一个基类。 结合一个简单例子讲解 Visitor利用了OOP的多态特性来处理对多个编程接口不同的对象进行访问的问题,简单而富弹性。与传统的方法相比,消除了数量庞大的if和instanceof语句,结构更加清晰。 其次也可以看到,遍历数据逻辑,和数据处理逻辑被完全隔离,在数据遍历相同的情况下,我们只要创建多个Visitor,而不必在每次数据的遍历处理过程中重复数据遍历代码,这对消除代码冗余有很大帮助,尤其是遍历代码涉及复杂的算法或初始化和释放资源操作的时候,效果相当明显。

Visitor模式应用举例 典型应用在编译器语法语义分析。

Visitor Vs Iterator Visitor和Iterator都是用于数据遍历的,其差 异主要是由所采取的数据读取模式不同而引起。 Visitor使用的推(Push)模型,而Iterator用的则是 拉(Pull)模型。 拉模型更加简单直观,但是推模型能充分利用 OOP的多态来简化代码,优化体系结构。 Iterator可以将数据遍历逻辑封装起来,从而和处理逻辑隔离,但是无法解决访问对象不同情况下的问题,仍然需要采用传统的if和instanceof语句。此外,Iterator采用的是拉模型,故无法实现反控。

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 解释器模式 意图 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 适用性 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。而当存在以下情况时该模式效果最好: 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。

何时引入定制语言 程序必须解释执行任意的字符指令 程序以字 符指令为输入,根据指令执行不同的动作。例 如数学运算和数理统计方面的软件、数据库的 DDL等。 程序必须产生多种多样的输出结果 尽管这些 输出结果和执行流程各异,但它们执行所包含 的操作步骤却是相同的。故需要一种语言来描 述相关的操作。如报表软件、数据库的DML、 转换XML文档的XSL等。 Ddl: data definition language; DML: data manipulation language.

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 中介者模式 意图 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 适用性 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。 想定制一个分布在多个类中的行为,而又不想生成太多的子类。

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 策略模式 意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 适用性 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。 一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。 完成某个功能有多个选择方案,比如从A到B,可以选择坐火车,也可以选择坐飞机,选择是基于上下文环境的。

Template Pattern 意图 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Templ ate Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 适用性 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke 和Johnsn 所描述过的“重分解以一般化”的一个很好的例子。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。 控制子类扩展。模板方法只在特定点调用“h o o k ”操作(参见效果一节),这样就只允许在这些点进行扩展。 下面关于行为模式,行为模式涉及到算法和对象间职责的分配。不仅描述对象或者类的模式,还描述了他们之间的通信模式。 模板模式,具体由子类实现的步骤叫做钩子操作,体现了父类对子类扩展的控制