第27章 结构型模式大PK
27.1 代理模式 VS 装饰模式
27.1.1 代理模式
(1)场景:客人找运动员代理要求安排运动员参加比赛
(2)说明:代理人有控制权,可以拒绝客人的要求,也可以答应安排,甚至自己下去跑(因为有些运动员本身就作自己的代理)
【编程实验】找代理安排运动员比赛

//结构型模式大PK——代理模式和装饰模式
//实例:找代理安排运动员比赛
#include <iostream>
#include <ctime>
using namespace std; //抽象运动员
class IRunner
{
public:
virtual void run() = ; virtual ~IRunner() {}
}; //运动员
class Runner : public IRunner
{
public:
void run()
{
cout << "运动员跑步,动作很潇洒" << endl;
}
}; //代理人(也与运动员一样,实现同一接口)
class RunnerAgent : public IRunner
{
Runner* runner;
public:
RunnerAgent(Runner* runner)
{
srand((int)time(NULL));
this->runner = runner;
} void run()
{
if((rand() % ) ==)
{
cout << "代理人同意安排运动员跑步" << endl;
runner->run();
}
else
{
cout << "代理人心情不好,不安排运动员跑步" << endl;
}
}
}; int main()
{
//定义一个运动员
Runner* runner = new Runner();
//定义代理人
IRunner* agent = new RunnerAgent(runner); //要求运动员跑步
cout << "===客人找到代理要求运动员去跑步" << endl; //为演示,比如洽谈了10次
for(int i=; i<; i++)
{
cout <<"第" <<i+ <<"次洽谈结果:";
agent->run();
cout << endl;
} delete runner;
delete agent; return ;
};
27.1.2 装饰模式
(1)装饰模式:对类的功能进行加强
【编程实验】安装喷气装置

//结构型模式大PK——代理模式和装饰模式
//实例:为飞机安装喷气动力装置
#include <iostream>
#include <ctime>
using namespace std; //飞行接口
class IFly
{
public:
virtual void fly() = ; virtual ~IFly() {}
}; //飞机
class AirPlane : public IFly
{
public:
void fly()
{
cout << "飞机正在飞行..." << endl;
}
};
//JetFly
class JetFly : public IFly
{
IFly* airPlane;
public:
JetFly(IFly* airPlane)
{
this->airPlane = airPlane;
}
void speedUp()
{
cout << "为飞机加装了喷气动力装置,正在加速中..." << endl;
}
void fly()
{
speedUp();
airPlane->fly();
}
};
int main()
{
//定义一架飞机
IFly* airPlane = new AirPlane();
//定义装饰类,对功能进行加强
IFly* jet = new JetFly(airPlane); cout << "===增加功能后的飞机" << endl; jet->fly(); delete jet;
delete airPlane; return ;
};
27.1.3 最佳实践
(1)装饰类对被装饰的类的行为没有决定权,只有增强作用。而代理可以控制对被代理人的访问。
(2)代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定(如是否可以调用真实角色,一般不对被代理功能当修饰,而是保证原汁原叶的调用。
(3)装饰模式在保证接口不变的情况下加强类的功能,它保证的是被修饰对象功能比原来丰富(当然也可以减弱),但不做准入条件和准入参数的过滤。
27.1.3 最佳实践
(1)装饰类对被装饰的类的行为没有决定权,只有增强作用。而代理可以控制对被代理人的访问。
(2)代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定(如是否可以调用真实角色,一般不对被代理功能当修饰,而是保证原汁原叶的调用。
(3)装饰模式在保证接口不变的情况下加强类的功能,它保证的是被修饰对象功能比原来丰富(当然也可以减弱),但不做准入条件和准入参数的过滤。
27.2 装饰模式 VS 适配器模式
27.2.1 用装饰模式描述丑小鸭
(1)丑小鸭首先是一只天鹅,具备了天鹅所有的行为和属性(即它从天鹅继承而来)
(2)只是小时候,又小、又脏,又不能飞行。随着时间推移,对其属性和行为进行加强,慢慢变成一只白天鹅。
【编程实验】丑小鸭变小天鹅的故事

//结构型模式大PK——装饰模式和适配器模式
//实例:丑小鸭变小天鹅
#include <iostream>
#include <ctime>
using namespace std; //天鹅接口
class Swan
{
public:
virtual void fly() = ; //会飞
virtual void cry() = ; //会叫
virtual void Appearance() = ; //外观 virtual ~Swan(){}
}; //丑小鸭(本质上是天鹅)
class UglyDuckling : public Swan
{
public:
//丑小鸭还比较小,不能飞
void fly()
{
cout << "不能飞" <<endl;
}
//丑小鸭的叫声
void cry()
{
cout << "叫声是克噜——克噜——克噜" << endl;
} //丑小鸭的外形
void Appearance()
{
cout << "外形是脏兮兮的白色,毛毛茸茸的大脑袋" <<endl;
}
}; //装饰类
class Decorator : public Swan
{
private:
Swan* swan;
public:
Decorator(Swan* swan)
{
this->swan = swan;
}
void fly()
{
swan->fly();
} void cry()
{
swan->cry();
} void Appearance()
{
swan->Appearance();
}
}; //具体的装饰类(外形美化)
class BeautifyAppearance : public Decorator
{
public:
BeautifyAppearance(Swan* swan):Decorator(swan){} //外表美化处理(重写该方法)
void Appearance()
{
//这里是重新实现,不再调用原来的Decorator::desAppearance()
cout << "外表是纯白色的,非常惹人喜爱" << endl;
}
}; //具体装饰类
class StrongBehavior :public Decorator
{
public:
StrongBehavior(Swan* swan):Decorator(swan){} //会飞行了
void fly()
{
//这里是完全重新实现了被装饰类飞的功能。
cout << "会飞行了!" << endl;
}
}; int main()
{
cout <<"===很久很久以前,这里有一只丑陋的小鸭子===" << endl;
Swan* duckling = new UglyDuckling(); //展示一下小鸭
duckling->Appearance();
duckling->cry();
duckling->fly(); cout <<"===小鸭子终于发现自己是一只天鹅===" << endl;
//首先外形变化
BeautifyAppearance duckling2(duckling);
StrongBehavior duckling3(&duckling2); duckling3.Appearance();
duckling3.cry();
duckling3.fly(); delete duckling; return ;
};
/*输出结果:
===很久很久以前,这里有一只丑陋的小鸭子===
外形是脏兮兮的白色,毛毛茸茸的大脑袋
叫声是克噜——克噜——克噜
不能飞
===小鸭子终于发现自己是一只天鹅===
外表是纯白色的,非常惹人喜爱
叫声是克噜——克噜——克噜
会飞行了!
*/
27.2.2 用适配器模式描述丑小鸭
(1)两个接口:鸭和天鹅。而丑小鸭就相当于适配器。
(2)为了演示适配器的使用,丑小鸭本质上是天鹅,所以应该把鸭子的接口转为天鹅的接口。即鸭子的源接口,目标接口为天鹅。以便让天鹅具备小鸭的一些特点。
【编程实验】一只与众不同的鸭子

//结构型模式大PK——装饰模式和适配器模式
//实例:一只与众不同的鸭子
#include <iostream>
#include <ctime>
using namespace std; //天鹅接口
class Swan
{
public:
virtual void behavior() = ; //其他行为,会飞
virtual void cry() = ; //会叫
virtual void Appearance() = ; //外观
}; //鸭子的接口
class Duck
{
public:
virtual void behavior() = ; //会游泳
virtual void cry() = ; //会叫
virtual void Appearance() = ; //外观 virtual ~Duck(){}
}; //白天鹅
class WhiteSwan : public Swan
{
public:
void cry()
{
cout << "叫声是克噜——克噜——克噜" << endl;
}
void Appearance()
{
cout << "外形是纯白色,惹人喜爱" << endl;
}
//其他行为
void behavior()
{
cout << "能够飞行" << endl;
}
}; //小鸭子
class Duckling : public Duck
{
public:
void cry()
{
cout << "叫声是嘎——嘎——嘎" << endl;
}
void Appearance()
{
cout << "外形是黄白相间,嘴长" << endl;
} //描述鸭子的其他行为
void behavior()
{
cout << "会游泳" << endl;
}
}; //丑小鸭相当于适配器的角色,丑小鸭本质上是天鹅,所以应该把鸭子
//的接口转为天鹅的接口。即鸭子的源接口,目标接口为天鹅
class UglyDuckling : public WhiteSwan
{
Duck* duck; //目标接口
public:
UglyDuckling(Duck* duck)
{
this->duck = duck;
}
//丑小鸭的叫声,直接从父类继承 //丑小鸭的外形,直接从父类继承 //其他行为
void behavior()
{
//本身会飞
WhiteSwan::behavior();
//学会鸭子的游泳
duck->behavior();
}
}; int main()
{
cout <<"===鸭妈妈有5个孩子,其中4个都是一个模样==="<< endl;
Duck* duck = new Duckling();
duck->cry();
duck->Appearance();
duck->behavior(); cout <<"===一只独特的小鸭子,模样是这样的==="<< endl;
UglyDuckling uglyDuckling(duck); //丑小鸭
uglyDuckling.cry();
uglyDuckling.Appearance();
uglyDuckling.behavior(); delete duck; return ;
};
/*输出结果:
===鸭妈妈有5个孩子,其中4个都是一个模样===
叫声是嘎——嘎——嘎
外形是黄白相间,嘴长
会游泳
===一只独特的小鸭子,模样是这样的===
叫声是克噜——克噜——克噜
外形是纯白色,惹人喜爱
能够飞行
会游泳
*/
27.2.3 最佳实践
(1)装饰模式包装的是自己的兄弟类,隶属于同一家族(相同的父类),而适配器模式则修饰的是非血缘关系类。把一个非本家族伪装成本家族的对象,注意是伪装,因此它的本质还是不同的接口对象。
(2)意图不同
装饰模式的意图是加强对象的功能,而适配器模式关注的是转化,两个对象之间的接口转化。
(3)所作用的对象不同
①装饰模式装饰的对象必须是自己的同宗,也就是相同的父类,只要在具有相同的属性和行为情况下,才能比较行为是增加或减弱。
②适配器模式则必须是两个不对象接口对象,因为它着重于转换
(4)场景不同
①装饰模式只要是想增强功能的,都可以用。
②适配器模式则是一个补救模式,一般出现在系统成熟或己经构建完毕的项目中,作为一个紧急处理手段采用。
(5)扩展性不同
装饰模式容易扩展,如果不需要修饰某对象了,可以随时拿掉,而且装饰类也可以继续扩展。但适配器模式就不同,它在两个不同对象之间架起一座沟通的桥染,建立容易,去掉时需要从系统整体考虑是否能够撤销。
第27章 结构型模式大PK的更多相关文章
- 第28章 行为型模式大PK
		
27.1 策略模式 VS 命令模式 27.1.1 策略模式实现压缩算法 //行为型模式大PK——策略模式和命令模式 //实例:用策略模式实现压缩算法 #include <iostream> ...
 - 第26章 创建型模式大PK
		
26.1 工厂方法模式 VS 建造者模式 26.1.1 按工厂方法建造超人 (1)产品:两类超人,成年超人和未成年超人. (2)工厂:这里选择简单工厂 [编程实验]工厂方法建造超人 //创建型模式大P ...
 - Java设计模式之七大结构型模式(附实例和详解)
		
博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...
 - (转)Java经典设计模式(2):七大结构型模式(附实例和详解)
		
原文出处: 小宝鸽 总体来说设计模式分为三大类:创建型模式.结构型模式和行为型模式. 博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则.设计模式的六大原则是设计模式 ...
 - Java经典设计模式之七大结构型模式(附实例和详解)
		
博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...
 - Java经典设计模式之七大结构型模式
		
转载: Java经典设计模式之七大结构型模式 博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以 ...
 - Go语言实现的23种设计模式之结构型模式
		
摘要:本文主要聚焦在结构型模式(Structural Pattern)上,其主要思想是将多个对象组装成较大的结构,并同时保持结构的灵活和高效,从程序的结构上解决模块之间的耦合问题. 本文分享自华为云社 ...
 - 设计模式之美:Structural Patterns(结构型模式)
		
结构型模式涉及到如何组合类和对象以获得更大的结构. 结构型类模式采用继承机制来组合接口实现. 结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法. 因为 ...
 - .NET设计模式(15):结构型模式专题总结(转)
		
摘要:结构型模式,顾名思义讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象,从而实现新的功能(对象结构型模式).这些结构型模式,它们在某些方面具有很大的相似 ...
 
随机推荐
- 拖放 js
			
之前被小伙伴问自己能不能写一个简单的原生的 我稍微犹豫了下 这次重新学习下拖拽的过程 分享下 参考 JavaScript高级程序设计 必要的准备 自定义事件(实现事件模型) 简单来说事件模型就 ...
 - [js开源组件开发]network异步请求ajax的扩展
			
network异步请求ajax的扩展 在日常的应用中,你可能直接调用$.ajax是会有些问题的,比如说用户的重复点击,比如说我只希望它成功提交一次后就不能再提交,比如说我希望有个正在提交的loadin ...
 - go语言 类型:整型
			
整型是所有编程语言里最基础的数据类型.
 - JS去掉首尾空格 简单方法大全(原生正则jquery)
			
JS去掉首尾空格 简单方法大全 var osfipin= ' http://www.cnblogs.com/osfipin/ '; //去除首尾空格 osfipin.replace(/(^\s*)|( ...
 - [deviceone开发]-企业OA项目开源分享
			
一.简介 是一个真实的企业OA项目改造的开源项目,几乎涵盖了所有常用的组件,包括环信实现在线聊天等功能,类似微信的朋友圈功能,自定义的智能搜索等,而且这个是真实的通过Http链接后台web服务,里面很 ...
 - atitit.身份认证解决方案attilax总结
			
atitit.身份认证解决方案attilax总结 1.1. 身份认证1 1.2. basic认证1 1.2.1. 编程实现basic客户端2 1.3. digest认证机制3 1.4. SSL认证3 ...
 - ubuntu环境变量
			
在Ubuntu中有如下几个文件可以设置环境变量1./etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行.2. ...
 - xmpp整理笔记:聊天信息的发送与显示
			
任何一个信息的发送都需要关注两个部分,信息的发出,和信息在界面中的显示 往期回顾: xmpp整理笔记:环境的快速配置(附安装包) http://www.cnblogs.com/dsxniubilit ...
 - PCM(Pulse-code modulation)脉冲编码调制
			
在音频处理中,我们会经常听到PCM数据,那么什么是PCM数据呢? PCM数据就是模拟信号经过PCM以后的数字信号,PCM就是把音频信号由模拟信号(时间连续,取值连续)转为数字信号(时间离散,取值离散) ...
 - AndroidAnnotations配置--Android studio
			
1.引入对android-apt的依赖.在全局build.gradle中文件中添加以下代码.(Project目录下的build.gradle) repositories { mavenCentral( ...