0%

【SE】软件设计模式例题总结

【考试向】13种设计模式的 PPT+网上+书上 的各种例题搜集汇总

【行为型】策略模式

定义

策略模式定义了算法族,分别封装起来,让它们之间可以相互替换,让算法的变化独立于算法的客户。

类图与使用场景

image.png

  • 想使用对象中 各种不同的算法变体,并且希望能在运行时切换算法
  • 有许多 仅在执行某些行为时略有不同的相似类
    • 将不同行为抽取到一个独立类(Strategy)层次结构中,并将原始类组合成一个
  • 算法在Context中的逻辑不重要,可以用策略模式将类的业务逻辑与算法实现细节隔离开来
  • 类中使用了复杂条件运算符(if-else)以在同一算法的不同变体中切换

与其他模式的关系

  • 通过某些行为来参数化对象:命令模式、策略模式

  • 装饰者模式更改对象的外表,策略模式更改其本质

  • 模板方法 基于继承:允许通过扩展子类的部分内容改变部分算法;

    • 策略模式 基于组合:通过相应行为提供的不同策略来改变对象的行为;

      • 模板方法 在层次上运作,静态

      • 策略模式在对象层次上运作,允许运行时动态切换

  • 状态模式可以视为策略模式的扩展,都基于组合

    • 都通过将部分工作 委 托 给 对象 来改变在不同情景下的行为

      • 策略模式:这些对象(具体策略)之间完全相互独立,不知道其他对象存在;客户知道具体策略

      • 状态模式:没有限制具体状态之间的依赖,运行自行改变在不同情景下的状态;客户不知道具体状态


样例

  • 找出修改频率较高的算法
  • 声明该算法所有变体的通用策略接口Stategy
  • 将算法逐一抽取到各自的类中,都必须implements策略接口
  • Context类中添加一个成员变量保存Stategy的引用;提供setter方法便于修改它;

例1:导游路线规划

一个导游程序,有多种规划路线的功能,包括规划公路路线、规划步行路线、规划公共交通路线,但是不久之后,可能要规划其他路线,比如骑行路线等等

image.png

例2:出行方式

人的出行方式多种。假如你需要前往机场。你可以选择乘坐公共汽车、预约出租车或骑自行车。这些就是你的出行策略。

image.png

例3:电影院售票

某电影院售票系统为不同类型的用户提供不同打折方式(Discount),学生凭学生证享受8折优惠(StudentDiscount),儿童享受减免10元优惠(ChildrenDiscount),VIP用户除享受半价优惠还可积分(VIPDiscount)

image.png

例4:税额计算

一个电子商务系统,其中有一个控制器对象(TaskController),用于处理销售请求,能够确认何时有人在请求销售订单,并将请求转给SalesOrder对象处理。SalesOrder对象的功能包括:允许客户通过GUI填写订单,处理税额的计算,处理订单和打印销售收据。新需求:要处理多种税额计算的方法,美国、加拿大、中国三个国家的税收方法

image.png

例5:计算器

设计一个简单计算器,能实现两个操作数的加减乘除四种运算

例6:图书打折方式

一个贩卖各类书籍的电子商务网站的购物车(Shopping Cart)系统计算本次购物金额的方法有多种,比如:对所有的教材类图书实行每本1元的折扣;对连环画类图书提供每本7%的促销折扣;对非教材类的计算机图书有3%的折扣;对其余的图书没有折扣


例7:会员打折方式

现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的高级会员提供每本20%的促销折扣;对中级会员提供每本10%的促销折扣;对初级会员没有折扣。

image.png

例8:各种飞机

某软件公司现欲开发一款飞机模拟系统,该系统主要模拟不同种类飞机的飞行特征与起飞特征。还能支持模拟更多种类的飞机。

image.png

对比书上的例子(照喵画虎)

image.png

例9:图片滤镜

为了实现一些特殊的显示效果,某公司欲开发一款手机数码照片处理软件,在该软件中为照片(Photograph)提供了多种滤镜(Filter)效果,例如黑白滤镜(BlackWhiteFilter)、单色滤镜(MonochromaticFilter)、怀旧滤镜(NostalgicFilter)等,不同的滤镜通过不同的算法对照片进行美化,该软件可以灵活地增加一些新的滤镜效果。

例10:加密

某系统需要对重要数据(如用户密码)进行加密,并提供了几种加密方案(如凯撒加密、DES加密等),对该加密模块进行设计,使得用户可以动态选择加密方式


例11:排序策略问题

某系统提供了一个用于对数组数据进行操作的类,该类封装了对数组的常见操作,如查找数组元素、对数组元素进行排序等。现以排序操作为例,使用策略模式设计该数组操作类,使得客户端可以动态地更换排序算法,可以根据需要选择冒泡排序或选择排序或插入排序,也能够灵活地增加新的排序算法。

【行为型】观察者模式

定义

定义了对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖者都会收到通知并且自动更新

类图与使用场景

image.png

  • 当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的
  • 当应用中的一些对象必须观察其他对象时

与其他模式的关系

样例

关键词:通知, 出版&订阅一个对象变化,通知其他多个对象它变化了

拥有一些值得关注的状态的对象通常被称为目标,由于它要将自身的状态改变通知给其他对象,我们也将其称为发布者(publisher,也即subject)。所有希望关注发布者状态变化的其他对象被称为订阅者(subscribers,也即observer)。为发布者类添加订阅机制,让每个对象都能订阅或取消订阅发布者事件流。该机制包括

1)一个用于存储订阅者对象引用的列表成员变量

2)几个用于添加或删除该列表中订阅者的公有方法。

例1:股票价格通知

当股票购买者所购买的某只股票价格变化幅度达到5%时,系统自动发送通知给购买该股票的股民

image.png

例2:地震监测报警

现需要开发一个地震监测报警系统,如果接收到相关监测机构发来的预警数据,系统将作出反应,将信号传递给响应设备,如广播自动播放报警信息、逃生指示灯亮起、安全门锁打开、电梯自动停用等,每一种响应设备的行为由专门的程序来控制。支持将来引入新类型的响应设备。

例3:电子商务系统

一个电子商务系统,当一个新的消费用户加入系统,希望做以下两个操作:向消费者发送一封欢迎邮件;向邮局查证消费者地址

image.png

例4:机房监控系统

如果机房达到一定指定温度,传感器将作出反应,将信号传递给响应设备,如警示灯将闪烁,报警器将发出警报,安全逃生门将自动开启、隔热门将自动关闭,每一响应设备的行为由专门的程序来控制,支持将来引入新类型的响应设备。

image.png

例5:多人联机对战

某在线游戏支持多人联机对战,每个玩家都可以加入某一战队组成联盟,当战队中某一成员受到敌人攻击时将给所有盟友发送通知,盟友收到通知后将作出响应

image.png


【行为型】状态模式

定义

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类

类图与使用场景

image.png

  • 对象的行为依赖于它的状态(如某些属性值),状态的改变将导致行为的变化
  • 在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。

与其他模式的关系

  • 在状态模式中, 特定状态(可以)知道其他所有状态的存在,且能触发从一个状态到另一个状态的转换;行为对客户来说是透明的,客户不知道状态对象的存在

    • 策略则几乎完全不知道其他策略的存在。

    • 状态可被视为策略的扩展。两者都基于组合机制:它们都通过将部分工作委派给“帮手”对象来改变其在不同情景下的行为。策略使得这些对象相互之间完全独立,它们不知道其他对象的存在。 但状态模式没有限制具体状态之间的依赖,且允许它们自行改变在不同情景下的状态。

样例

关键词:状态动作使得状态转换

  • 为对象的一个 所有可能状态 新建一个类(ConcreteState),将所有该状态的对应行为抽取到这些类中
  • Context类持有State/ConcreteState成员变量

例1:信用卡账户

信用卡业务系统,账户(Account)是核心类之一,账户存在三种状态,且在不同状态下账户存在不同的行为,具体说明如下:

  • (1) 如果账户中余额大于等于0,则账户的状态为正常状态(Normal State),此时用户既可以向该账户存款也可以从该账户取款;

  • (2) 如果账户中余额小于0,并且大于-2000,则账户的状态为透支状态(Overdraft State),此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息;

  • (3) 如果账户中余额等于-2000,那么账户的状态为受限状态(Restricted State),此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息;

  • (4) 根据余额的不同,以上三种状态可发生相互转换

    • 分析:账户==Context,三种状态 == ConcreteState;封装进状态的动作:存款、取款、利息计算、根据余额进行状态转换

image.png

例2:开关

如果某系统要求两个开关对象(Context)要么都处于开的状态,要么都处于关的状态,在使用时它们的状态必须保持一致,开关可以由开转换到关,也可以由关转换到开

  • 分析:多个环境对象可能需要共享同一个状态,如果希望在系统中实现多个环境对象共享一个或多个状态对象,那么需要将这些状态对象定义为环境类的静态成员对象

  • Switch里的三个state都是静态成员变量(所以应该还有下划线表示才对

image.png

例3:屏幕放大

一个屏幕放大镜工具: 用户单击“放大镜”按钮之后屏幕将放大一倍,再点击一次“放大镜”按钮屏幕再放大一倍,第三次点击该按钮后屏幕将还原到默认大小

  • 定义三个屏幕状态类NormalState、LargerState和LargestState来对应屏幕的三种状态,分别是正常状态、二倍放大状态和四倍放大状态,屏幕类Screen充当Context类

image.png

例4:纸牌游戏

某纸牌游戏中,人物角色具有入门级(Primary),熟练级(Secondary),高手级(Professional)和骨灰级(Final)四种等级,角色的等级与积分相对应,游戏胜利将增加积分,失败则扣除积分,入门级具有最基本的游戏功能play(),熟练级增加了游戏胜利积分加倍功能doubleScore(),高手级在熟练级基础上再增加换牌功能changeCards(),骨灰级在高手级基础上再增加偷看他人的牌的功能peekCards()

  • 第一眼儿看差点以为是策略模式;但是要注意“角色的等级与积分相对应”,说明等级会随着积分的改变而发生改变,游戏又对积分有各种操作;所以更应该是状态模式

image.png

例5:线程状态

多线程存在 5 种状态,分别为新建状态、就绪状态、运行状态、阻塞状态和死亡状态,各个状态当遇到相关方法调用或事件触发时会转换到其他状态

image.png

例6:传输门

传输门具有Open(打开)、Closed(关闭)、Opening(正在打开)、StayOpen(保持打开)、Closing(正在关闭)五种状态。触发状态的转换事件有click、complete和timeout三种。


例7:抽奖活动

编写程序完成APP抽奖活动,具体要求如下:

(1)加入每参加一次这个活动要扣除用户50积分,中奖概率是10%

(2)奖品数量固定,抽完就不能抽奖

(3)活动有4个状态:可以抽奖、不能抽奖、发放奖品和奖品领完


【行为型】模板方法模式

定义

在一个方法中定义了一个算法的骨架,将一些步骤延迟到子类中。这样子类在不改变算法结构的情况下,可以重新定义算法中的某些步骤

类图与使用场景

image.png

  • 只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时
  • 当多个类的算法除一些细微不同之外几乎完全一样时
  • 将算法分解为一系列步骤
  • 将这些步骤改写为方法
    • 步骤可以是 抽象 的,也可以有一些默认的实现。
  • 在“模板方法”中依次调用这些方法。
  • 为了能够使用算法,客户端需要自行提供子类并实现所有的抽象步骤。如有必要还需重写一些步骤(但这一步中不包括模板方法自身)。

与其他模式的关系

  • 工厂方法 是 模板方法的一种特殊形式。工厂方法可以作为一个大型模板方法的一个步骤

  • 模板方法基于继承机制:它允许你通过扩展子类中的部分内容来改变部分算法。

    • 策略基于组合机制:你可以通过对相应行为提供不同的策略来改变对象的部分行为。

      • 模板方法在类层次上运作,因此它是静态的。

      • 策略在对象层次上运作,因此允许在运行时切换行为。

样例

关键词:一系列步骤流程不同类只有某些步骤相似但不同

  • 分析目标算法,确定能否将其分解为多个步骤。从所有子类的角度出发,考虑哪些步骤能够通用,哪些步骤各不相同
  • 创建抽象基类并声明一个模板方法和代表算法步骤的一系列抽象方法。 在模板方法中根据算法结构依次调用相应步骤。可用 final 修饰模板方法以防止子类对其进行重写。
  • 可考虑在算法的关键步骤之间添加钩子
  • 为每个算法变体新建一个具体子类,它必须实现所有的抽象步骤,也可以重写部分可选步骤

例1:数据库操作

对数据库的操作一般包括连接、打开、使用、关闭等步骤,在数据库操作模板类中我们定义了connDB(),openDB(),useDB(),closeDB()四个方法分别对应这四个步骤,对于不同类型的数据库(如SQLserver和Oracle),其余操作步骤都一致,只是连接数据库connDB()方法有所区别

  • 分析:将四个步骤按顺序封装到一个方法里,那个在不同类中 不同的步骤 在方法外声明为抽象方法

image.png

例2:利息计算

给出一个利息计算流程,但流程中有个步骤 根据用户类型 不同计算利息的方式不同

image.png

例3:数据图表

一个数据图表显示功能包括三个步骤,(从数据源获取数据,数据转换为XML,以某种图表方式显示XML格式数据)支持多种数据源和多种图表显示方式如果已经是XML无需进行数据转换(说明有个钩子方法)

  • 分析:钩子方法能够作为条件 控制算法的流程

image.png

例4:豆浆制作

编写制作豆浆的程序,说明如下:

  • 制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎
  • 通过添加不同的配料,可以制作出不同口味的豆浆
  • 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样

image.png


【行为型】命令模式

定义

请求封装成对象,以便使用不同的请求、队列或日志来参数化其他对象。也支持可撤销的操作

类图与使用场景

image.png

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
  • 要支持命令的撤销(Undo)操作和恢复(Redo)操作
  • 系统需要将一组操作组合在一起形成宏命令。

image.png

与其他模式的关系

样例

例1:遥控器功能键

某遥控器提供了一些按键,使用户可以自定义按键功能,如功能键FunctionButton可用于调出菜单(ShowMenu),也可用于打开帮助界面(DisplayHelp),也可用于打开机顶盒(OpenSTB)。用户可以通过修改配置文件来改变按键的用途,使按键类与功能类之间解耦相同的按键可以对应不同的功能.

image.png

例2:公告板

一个基于windows平台的公告板系统,该系统提供一个主菜单(Menu),在主菜单中包含了一些菜单项(MenuItem),可以通过Menu类的addMenuItem()方法添加菜单项,菜单项的主要方法是click(),每一个菜单项包含一个抽象命令类,具体命令类包含OpenCommand(打开命令)、CreateCommand(创建命令)和EditeCommand(编辑命令)等,命令类内置有一个excute()方法,用于调用公告板系统界面类(BoardScrean)的open()、create()、edite()等方法,要使MenuItem类与BoardScreen类的耦合度降低

image.png

例3:餐馆点菜

场景:餐馆点菜。角色:1.接收者:厨师,是命令的真正执行者。本例分为两种:做热菜的厨师和做凉菜的厨师 2.服务员:负责命令和接收者的组装,并持有命令对象(菜单),最后启动命令的也是服务员 3.命令对象:A、每一道菜是个命令对象;B、菜单(组合对象,由多道菜组成)

image.png

例4:桌面版应用程序

一提供了一系列自定义功能键,用户可以通过这些功能键来实现一些快捷操作。发现不同的用户可能会有不同的使用习惯,例如有的人喜欢将第一个功能键设置为“打开帮助文档”,有的人则喜欢将该功能键设置为“最小化至托盘”,设计使用户能够灵活地进行功能键的设置

image.png

例5:计算器

简易计算器,可以实现简单的数学运算,还可以对运算实施撤销操作

image.png

例6:智能生活

(1)买一套智能家电,有照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装app就可以控制这些家电工作

(2)这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个app,分别控制,只希望有一个app就可以控制全部智能家电

  • 要实现一个app控制所有智能家电的需求,则每个智能家电厂家都要提供一个统一的接口给app调用,这时 就可以考虑命令模式

  • 命令模式可将“动作的请求者”从“动作的执行者”对象中解耦出来

  • 动作的请求者是手机app,动作的执行者是每个厂商的一个家电产品


【行为型】迭代器模式

【创建型】工厂方法模式

定义

定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,让类把实例化推迟到子类

样例

例1:图片读取器

现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReader),如GIF图片读取器(GifReader)用于读取GIF格式的图片、JPG图片读取器(JpgReader)用于读取JPG格式的图片。图片读取器对象通过图片读取器工厂ImageReaderFactory来创建,ImageReaderFactory是一个抽象类,用于定义创建图片读取器的工厂方法,其子类GifReaderFactory和JpgReaderFactory用于创建具体的图片读取器对象

image.png

例2:日志记录器

某日志记录器 要求支持多种日志记录方式,如文件日志记录(FileLog)、数据库日志记录(DatabaseLog)等;用户可根据需要动态地选择日志记录方式 ( 我甚至觉得这个题用策略模式也不是不可以?)

image.png

例3:电视机工厂

有一电视机工厂,生产各种电视机。现要将原有的工厂进行分割,为每种品牌的电视机提供一个子工厂,海尔工厂专门负责生产海尔电视机,海信工厂专门负责生产海信电视机;如果需要生产其他某个品牌电视机,只需要对应增加一个新的该品牌电视机工厂即可,而原有的工厂无须做任何修改,使得整个系统具有更加的灵活性和可扩展性

【创建型】抽象工厂模式

定义

提供一个接口,用来创建 相关或依赖对象的家族,而不需要明确指定具体类

样例

例1:数据库

某系统为了改进数据库操作的性能,自定义数据库连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象,如提供Oracle或MySQL专用连接类和语句类,而且用户可以通过配置文件等方式根据实际需要动态地选择系统数据库

image.png

例2:操作系统

创建在不同操作系统的视窗环境下都能够运行的系统两种操作系统:windows和unix

  • windows操作系统下,使用具有windows风格的视窗构件(这里设为windowsButton对象和WindowsText对象)

  • Unix操作系统下,使用具有Unix风格的视窗构件UnixButton对象和UnixText对象

  • 如何进行设计,使得 1,当需要增加对新操作系统的支持时(如系统还需要支持Solaris),现有代码不必修改(符合“开-闭原则”) 2,在系统的设计中约束用户使用的各种构件一定属于同一操作系统(不会出现将WindowsButton和UnixText一起使用这种情况)

image.png

例3:动物游戏

在一个电脑游戏中,存在着美洲和非洲两块大陆。美洲大陆上有食肉动物(美洲虎)和食草动物(美洲羊) ;非洲大陆上有食肉动物(非洲虎)和食草动物(非洲羊)。电脑游戏的应用逻辑中需要实现这样的场景

  • 根据当前主人公角色所处大陆(美洲或非洲)来初始化当前游戏中的食肉动物和食肉动物
  • 食肉动物开始追捕食草动物

image.png

例4:驱动

设计一个系统来显示和打印数据库中读出的图形,并满足:根据当前所使用硬件的配置来选择驱动——速度快的机器选择高分辨率的显示、打印驱动,速度慢的选择低分辨率的驱动:

驱动类型 在低配置硬件情况下 在高配置硬件情况下

显示驱动 LRDD HRDD

打印驱动 LPPD HPPD

image.png

【创建型】单件模式

定义

确保类只有一个实例,并提供一个全局的访问点

多线程处理

双重检查加锁的理解

假如在某一瞬间线程A和线程B都在调用getInstance()方法,此时instance对象为null值,均能通过instance == null的判断(第一重检查)。由于实现了synchronized加锁机制,线程A进入synchronized锁定的代码中执行实例创建代码,线程B处于排队等待状态,必须等待线程A执行完毕后才可以进入synchronized锁定代码。但当A执行完毕时,线程B并不知道实例已经创建,如果没有第二重检查的话,将继续创建新的实例,导致产生多个单例对象,违背单例模式的设计思想,因此需要进行进一步改进,在 synchronized中再进行一次(instance == null)判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class LazySingleton{
private static volatile static LazySingleton instance = null;
//被volatile修饰的成员变量可以确保多个线程都能够正确处理
private LazySingleton(){}
public static LazySingleton getInstance(){
if(instance == null){//第一重检查
synchronized(LazySingleton.class){ //加锁
if(instance == null){ //第二重检查
instance = new LazySingleton();
}
}
}
return instance;
}
}

类图

  • 急切实例化

    image.png

  • 延迟实例化

    image.png

  • 急切实例化和延迟实例化的比较

    • 急切:在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于延迟。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该 对象就需要创建,因此从资源利用效率角度来讲,不及延迟,而且在系统加载时由于需要创建单例对象,加载时间可能会比较长

    • 延迟:在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处 理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源 初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响

样例

例1:负载均衡器

Sunny软件公司承接了一个服务器负载均衡(Load Balance)软件的开发工作,该软件运行在一台 负载均衡服务器上,可以将并发访问和数据流量分发到服务器集群中的多台设备上进行并发处理,提高系统的整体处理能力,缩短响应时间。由于集群中的服务器需要动态删减,且客户端请求需要统一分发,因此需要确保负载均衡器的唯一性,只能有一个负载均衡器来负责 服务器的管理和请求的分发,否则将会带来服务器状态的不一致以及请求分配冲突等问题。如何确保负载均衡器的唯一性是该软件成功的关键

image.png

1
2
3
4
5
6
7
8
9
10
11
public class LoadBalancer{
private static LoadBalancer instance;
private List serverList = new ArrayList();
private LoadBalancer(){}
public static LoadBalancer getLoadBalancer(){
if(instance == null){
instance = new LoadBalancer();
}
return instance;
}
}

例2:文档窗口

设计一个多文档窗口(注:在Java AWT/Swing开发中可使用JDesktopPane和JInternalFrame来实现),要求在主窗体中某个内部子窗体只能实例化一次,即只能弹出一个相同的子窗体

  • 单件模式用在子窗体上

image.png

例3:回收站

windows回收站的创建模拟 在整个视窗系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,不管如何双击“回收站”图标,打开的回收站窗口始终是唯一的一个

例4:网络计数器

网站计数器是WEB应用程序的一项基本功能,用于统计使用网站或者应用程序的人数,可反映出网站或者应用程序的受欢迎程序,对于电子商务网站可信度的研究有一定的参考价值

【结构型】适配器模式

样例

例1:🐕

现需要设计一个可以模拟各种动物行为的机器人,在机器人中定义了一系列方法,如机器人叫喊方法cry()、机器人移动方法move()等。如果希望在不修改已有代码的基础上使得机器人能够像狗一样叫,像狗一样跑

【结构型】组合模式

样例

例1:

在水果盘(Plate)中有一些水果,如苹果(Apple)、香蕉(Banana)、梨子(Pear),当然大水果盘中还可以有小水果盘,现需要对盘中的水果进行遍历(吃),当然如果对一个水果盘执行“吃”方法,实际上就是吃其中的水果

【结构型】装饰者模式

【结构型】外观模式