29.1 策略模式 VS 桥梁模式

29.1.1 策略模式

【编程实验】用策略模式实现邮件发送

(1)有文本和超文本两种格式的邮件,将这两种格式封装成两种不同的发送策略

(2)文本邮件和超文本邮件分别是两种不同格式的邮件的封装。MailServer是一个环境角色,它接收一个MailTemplate对象,并通过sendMail方法将邮件发送出去。

//跨战区大PK——策略模式和桥接模式
//实例:用策略模式实现邮件发送
#include <iostream>
#include <string> using namespace std; //抽象邮件
class MailTemplate
{
protected:
string from; //邮件发件人
string to; //收件人
string subject; //邮件标题
protected:
string context; //邮件内容
public:
MailTemplate(string from, string to,
string subject, string context)
{
this->from = from;
this->to = to;
this->subject = subject;
this->context = context;
} string getFrom(){return from;}
void setFrom(string value){from = value;} string getTo(){return to;}
void setTo(string value){to = value;} string getSubject(){return subject;}
void setSubject(string value){subject = value;} void setContext(string value){context = value;}
virtual string getContext() = ;
}; //文本邮件
class TextMail : public MailTemplate
{
public:
TextMail(string from, string to,
string subject, string context):MailTemplate(from, to, subject, context)
{
} string getContext()
{
//文本类型设置邮件的格式为text/plain
context = "\n Context-type: text/plain;charset=GB2312\n"
+ context;
//同时对邮件进行base64编码处理,这里用一句话代替
context += "\n邮件格式为:文本格式";
return context;
}
}; //超文本邮件
class HtmlMail : public MailTemplate
{
public:
HtmlMail(string from, string to,
string subject, string context):MailTemplate(from, to, subject, context)
{
} string getContext()
{
//超文本类型设置邮件的格式为multipart/mixed
context = "\n Context-type: multipart/mixed;charset=GB2312\n"
+ context;
//同时对邮件进行HTML检查,是否有类似未关闭的标答
context += "\n邮件格式为:超文本格式";
return context;
}
}; //邮件服务器(环境角色类)
class MailServer
{
private:
MailTemplate* mail;
public:
MailServer(MailTemplate& mt)
{
mail = &mt;
} //发送邮件
void sendMail()
{
cout << "====正在发送的邮件信息====" << endl;
//发件人
cout << "发件人:" << mail->getFrom()<< endl;
//收件人
cout << "收件人:" << mail->getTo()<< endl;
//邮件标题
cout << "邮件标题:" << mail->getSubject()<< endl;
//邮件内容
cout << "邮件内容:" << mail->getContext()<< endl;
}
}; int main()
{
//创建一封超文本格式的邮件
MailTemplate* txtMail = new HtmlMail("a@a.com", "b@b.com",
"外星人攻击地球了", "结局是外星人被地球人打败了!");
//创建邮件服务器
MailServer mailServ(*txtMail);
//发送邮件
mailServ.sendMail(); return ;
};
/*输出结果:
====正在发送的邮件信息====
发件人:a@a.com
收件人:b@b.com
邮件标题:外星人攻击地球了
邮件内容:
Context-type: multipart/mixed;charset=GB2312
结局是外星人被地球人打败了!
邮件格式为:超文本格式
*/

29.1.2 桥梁模式

【编程实验】用桥梁模式实现邮件发送

(1)增加了SendMail和Postfix两种邮件服务器的实现类,他们都从MailServer继承。

(2)这样邮件服务器与邮件模板就可以独立变化

//跨战区大PK——策略模式和桥接模式
//实例:用桥接模式实现邮件发送
#include <iostream>
#include <string> using namespace std; //抽象邮件
class MailTemplate
{
protected:
string from; //邮件发件人
string to; //收件人
string subject; //邮件标题
protected:
string context; //邮件内容
public:
MailTemplate(string from, string to,
string subject, string context)
{
this->from = from;
this->to = to;
this->subject = subject;
this->context = context;
} string getFrom(){return from;}
void setFrom(string value){from = value;} string getTo(){return to;}
void setTo(string value){to = value;} string getSubject(){return subject;}
void setSubject(string value){subject = value;} void setContext(string value){context = value;}
virtual string getContext() = ; //允许增加邮件发送标志
void add(string sendInfo)
{
context =sendInfo + context;
}
}; //文本邮件
class TextMail : public MailTemplate
{
public:
TextMail(string from, string to,
string subject, string context):MailTemplate(from, to, subject, context)
{
} string getContext()
{
//文本类型设置邮件的格式为text/plain
context = "\nContext-type: text/plain;charset=GB2312\n"
+ context;
//同时对邮件进行base64编码处理,这里用一句话代替
context += "\n邮件格式为:文本格式";
return context;
}
}; //超文本邮件
class HtmlMail : public MailTemplate
{
public:
HtmlMail(string from, string to,
string subject, string context):MailTemplate(from, to, subject, context)
{
} string getContext()
{
//超文本类型设置邮件的格式为multipart/mixed
context = "\nContext-type: multipart/mixed;charset=GB2312\n"
+ context;
//同时对邮件进行HTML检查,是否有类似未关闭的标答
context += "\n邮件格式为:超文本格式";
return context;
}
}; //邮件服务器(相当于桥接模式的抽象化角色)
class MailServer
{
protected:
MailTemplate* mail;
public:
MailServer(MailTemplate& mt)
{
mail = &mt;
} //发送邮件
virtual void sendMail()
{
cout << "====正在发送的邮件信息====" << endl;
//发件人
cout << "发件人:" << mail->getFrom()<< endl;
//收件人
cout << "收件人:" << mail->getTo()<< endl;
//邮件标题
cout << "邮件标题:" << mail->getSubject()<< endl;
//邮件内容
cout << "邮件内容:" << mail->getContext()<< endl;
}
}; //Postfix邮件服务器
class Postfix : public MailServer
{
public:
Postfix(MailTemplate& mt):MailServer(mt){} //修正邮件发送程序
void sendMail()
{
//增加邮件服务器信息
string context = "Received: from XXXX(unknow[xxx.xxx.xxx.xxx]) by ";
context += "aaa.aaa.com(Postfix) with ESMTP id 8DBCD172B8\n"; mail->add(context);
MailServer::sendMail();
}
}; //SendMail邮件服务器
class SendMail : public MailServer
{
public:
SendMail(MailTemplate& mt):MailServer(mt){} //修正邮件发送程序
void sendMail()
{
//增加邮件服务器信息
string context = "Received: (sendmail);7 Nov 2016 10:40:00 +100\n"; mail->add(context);
MailServer::sendMail();
}
}; int main()
{
//创建一封超文本格式的邮件
MailTemplate* txtMail = new HtmlMail("a@a.com", "b@b.com",
"外星人攻击地球了", "结局是外星人被地球人打败了!");
//创建邮件服务器
MailServer* mailServ = new Postfix(*txtMail);
//发送邮件
mailServ->sendMail(); return ;
};
/*输出结果:
====正在发送的邮件信息====
发件人:a@a.com
收件人:b@b.com
邮件标题:外星人攻击地球了
邮件内容:
Context-type: multipart/mixed;charset=GB2312
Received: from XXXX(unknow[xxx.xxx.xxx.xxx]) by aaa.aaa.com(Postfix) with ESMTP
id 8DBCD172B8
结局是外星人被地球人打败了!
邮件格式为:超文本格式
*/

29.1.3 小结

(1)策略模式是一个行为模式,旨在封装一系列的行为。可以把邮件的必要信息封装成一个对象,也就是一个行为,封装的格式不同,行为也就不同

(2)桥梁模式则是解决在不破坏封装的情况下将抽象和实现部分分离,让他们可以独立变化。

(3)策略模式使用继承和多态建立一套可以自由切换算法的模式,而桥梁模式必然有两个“桥墩”——抽象化角色和实现化角色,只要桥墩搭建好了,桥就有了。策略模式只有一个抽象角色,可以没有实现,也可以有很多实现。

29.2 外观模式 VS 中介者模式

29.2.1 中介者模式实现工资计算

(1)工资与职位、税收有关,职位提升工资就会增加,同时税收也增加,反之也成立。

(2)当税收比率增加,工资自然就减少,这三者之间两两都有关系,很适合用中介者模式

【编程实验】中介者模式实现工资计算

//跨战区大PK——中介者模式和外观模式
//实例:用中介者模式实现工资计算
#include <iostream>
#include <string> using namespace std; //***********************************************辅助接口类***************************
//职位接口
class IPosition
{
public:
virtual void promote() = ; //升职
virtual void demote() = ; //除职 virtual ~IPosition(){}
}; //工资接口
class ISalary
{
public:
//加薪
virtual void increaseSalary() = ;
//减薪
virtual void decreaseSalary() = ; virtual ~ISalary(){}
}; //税收接口
class ITax
{
public:
//税收上升
virtual void raise() = ;
//税收降低
virtual void drop() = ; virtual ~ITax(){}
}; //*****************************************中介者************************************************
//抽象中介者
class AbsMediator
{
public:
virtual void up(ISalary* salary) = ; //工资增加
virtual void up(ITax* tax) = ; //税收增加
virtual void up(IPosition* position) = ; //职位上升
virtual void down(ISalary* salary) = ; //工资减少
virtual void down(ITax* tax) = ; //税收降低
virtual void down(IPosition* position) = ; //职位降低
}; //*********************************************同事类**********************************
//抽象同事类
class AbsColleague
{
protected:
//每个同事类都对中介者非常了解
AbsMediator* mediator;
public:
AbsColleague(AbsMediator* mediator)
{
this->mediator = mediator;
}
}; //职位
class Position : public AbsColleague, public IPosition
{
public:
Position(AbsMediator* mediator): AbsColleague(mediator){} //职位上升
void promote()
{
mediator->up(this);
}
//职位下降
void demote()
{
mediator->down(this);
}
}; //工资
class Salary : public AbsColleague, public ISalary
{
public:
Salary(AbsMediator* mediator):AbsColleague(mediator){} void increaseSalary()
{
mediator->up(this);
} void decreaseSalary()
{
mediator->down(this);
}
}; //税收
class Tax : public AbsColleague, public ITax
{
public:
Tax(AbsMediator* mediator): AbsColleague(mediator){} void raise()
{
mediator->up(this);
} void drop()
{
mediator->down(this);
}
}; //中介者
class Mediator : public AbsMediator
{
private:
void upSalary()
{
cout << "工资翻倍,乐翻天" << endl;
} void upTax()
{
cout << "税收上升,为国家做贡献" << endl;
} void upPosition()
{
cout << "职位上升一级,狂喜" << endl;
} void downSalary()
{
cout << "经济不景气,降低工资" << endl;
} void downTax()
{
cout << "税收减少,国家收入减少" << endl;
} void downPosition()
{
cout << "官降三级,比自杀还痛苦" << endl;
} public:
//工资增加了
void up(ISalary* salary)
{
upSalary();
upTax();
} void up(ITax* tax)
{
upTax();
downSalary();
} void up(IPosition* position)
{
upPosition();
upSalary();
upTax();
} void down(ISalary* salary)
{
downSalary();
downTax();
} void down(ITax* tax)
{
downTax();
upSalary();
} void down(IPosition* position)
{
downPosition();
downSalary();
downTax();
}
}; int main()
{
//定义中介者
Mediator mediator; //定义各个同事类
IPosition* position = new Position(&mediator);
ISalary* salary = new Salary(&mediator);
ITax* tax = new Tax(&mediator); //职位上升了
position->promote(); cout << endl; //职位下降了
position->demote(); delete position;
delete salary;
delete tax; return ;
};
/*输出结果:
职位上升一级,狂喜
工资翻倍,乐翻天
税收上升,为国家做贡献 官降三级,比自杀还痛苦
经济不景气,降低工资
税收减少,国家收入减少
*/

29.2.2 外观模式实现工资计算

(1)工资计算是对基本工资、月奖金、绩效、考勤、税收等因素综合计算的结果。

(2)对于高管理层,是不希望看到中间的计算过程,他只要求传递一个人员和月份即可查询到某员工的工资,而不用关心其中复杂的计算过程,这很适合用外观模式来实现。

【编程实验】外观模式实现工资计算

//跨战区大PK——中介者模式和外观模式
//实例:用外观模式实现工资查询
#include <iostream>
#include <string>
#include <ctime> using namespace std; //考勤情况
class Attendance
{
int days;
public:
Attendance()
{
srand((int)time(NULL));
days = rand() & ;
}
//得到出勤天数
int getWorkDays(){return days;}
}; //奖金计算
class Bonus
{
private:
Attendance atte; //考勤情况
public:
//奖金
int getBonus()
{
//获得出勤情况
int workDays = atte.getWorkDays();
//奖金计算模型
int bonus = workDays * / ; return bonus;
}
}; //基本工资
class BasicSalary
{
public:
int getBasicSalary()
{
return ;
}
}; //绩效
class Performance
{
private:
BasicSalary basicSalary;
public:
int getPerformanceValue()
{
//随机绩效
int perf = rand() % ; return basicSalary.getBasicSalary() * perf /;
}
}; //税收
class Tax
{
public:
//交纳税收多少
int getTax()
{
//随机数量
return rand() & ;
}
}; //总工资计算
class SalaryProvider
{
private:
BasicSalary salary; //基本工资
Bonus bonus; //奖金
Performance perf; //绩效
Tax tax; //税收 public:
//获得用户的总收入
int totalSalary()
{
return salary.getBasicSalary() + bonus.getBonus() +
perf.getPerformanceValue() - tax.getTax();
}
}; //外观类
class HRFacade
{
private:
//总工资情况
SalaryProvider salaryProvider;
//考勤情况
Attendance attendance;
public:
//查询一个人的总收入
int querySalary(string name)
{
return salaryProvider.totalSalary();
} //查询一个员工一个月工作了多少天
int queryWorkDays(string name)
{
return attendance.getWorkDays();
}
}; int main()
{
//定义外观
HRFacade facade; cout << "====外系统查询总收入====" << endl;
int salary = facade.querySalary("张三");
cout <<"张三1月的总收放为:" << salary <<endl; //再查询出勤天数
cout << "====外系统查询出勤天数====" << endl;
int workDays = facade.queryWorkDays("张三");
cout <<"张三1月的出勤天数:" << workDays <<endl; return ;
};
/*输出结果:
====外系统查询总收入====
张三1月的总收放为:4000
====外系统查询出勤天数====
张三1月的出勤天数:29
*/

29.2.3 小结

(1)功能区别

  ①外观模式只是增加了一个门面,它对子系统来说没有增加任何功能,子系统可以脱离门面而独立存在,它是以封装和隔离为主要任务。

  ②中介者模式则增加了业务功能,它把各个同事类中的原有耦合关系移到了中介者,同事类不可能脱离中介者而独立存在。

(2)知晓状态不同

  对外观模式来说,子系统不知道有门面的存在,而对中介者来说,每个同事类都知道中介者存在,因为要依靠中介者调和同事之间的关系,它们对中介者非常了解。

(3)封装程序不同

  外观模式是一种简单的封装,所有的请求处理者委托给子系统完成,而中介者模式则需要有一个中心,由中心协调同事类完成,并且中心本身也完成部分业务,它属于更进一步的业务功能封装。

29.3 包装模式群大PK

(1)包装模式群包括装饰模式、适配器模式、外观模式、代理模式、桥接模式。他们中的有些角色基本自己不干活,都是通过委托的方式对一个对象或任务转发给其它类去做。

(2)代理模式:主要用在不希望展示一个对象内部细节的场景中,比如一个远程服务不需要把远程连接的所有细节暴露给外部模式,通过增加一个代理类,可以轻松地实现被代理类的功能封装。

(3)装饰模式:它倡导在不改变接口的前提下为对象增强功能或添加额外的职责,就扩展性而言,它比增加子类更加灵活。

(4)适配器模式:主要意图是转换接口,把一个对象的接口转换成另一个接口。

(5)桥接模式:在抽象层产生耦合,解决的是自行扩展的问题,它可以使两个有耦合关系的对象互不影响地扩展。

(6)外观模式:是一个粗粒度的封装,它提供一个方便访问子系统的接口,不具有任何的业务逻辑,仅仅是一个访问复杂系统的快速通道。没有它,子系统照样运行,有了它,只是更方便访问而己。

第29章 跨战区大PK的更多相关文章

  1. 第28章 行为型模式大PK

    27.1 策略模式 VS 命令模式 27.1.1 策略模式实现压缩算法 //行为型模式大PK——策略模式和命令模式 //实例:用策略模式实现压缩算法 #include <iostream> ...

  2. 第27章 结构型模式大PK

    27.1 代理模式 VS 装饰模式 27.1.1 代理模式 (1)场景:客人找运动员代理要求安排运动员参加比赛 (2)说明:代理人有控制权,可以拒绝客人的要求,也可以答应安排,甚至自己下去跑(因为有些 ...

  3. 第26章 创建型模式大PK

    26.1 工厂方法模式 VS 建造者模式 26.1.1 按工厂方法建造超人 (1)产品:两类超人,成年超人和未成年超人. (2)工厂:这里选择简单工厂 [编程实验]工厂方法建造超人 //创建型模式大P ...

  4. 第29章 电容触摸屏—触摸画板—零死角玩转STM32-F429系列

    第29章     电容触摸屏—触摸画板 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...

  5. 设计模式之行为类模式大PK

                                        行为类模式大PK 行为类模式包括责任链模式.命令模式.解释器模式.迭代器模式.中介者模式.备忘录模式.观察者模式.状态模式.策略 ...

  6. 设计模式之结构类模式大PK

                                      结构类模式大PK 结构类模式包括适配器模式.桥梁模式.组合模式.装饰模式.门面模式.享元模式和代理模式.之所以称其为结构类模式,是因 ...

  7. 设计模式之创建类模式大PK

                                        创建类模式大PK 创建类模式包括工厂方法模式.建造者模式.抽象工厂模式.单例模式和原型模式,他们能够提供对象的创建和管理职责.其 ...

  8. 存储过程 分页【NOT IN】和【>】效率大PK 千万级别数据测试结果

    use TTgoif exists (select * from sysobjects where name='Tonge')drop table Tongecreate table Tonge( I ...

  9. 普通方式 分页【NOT IN】和【>】效率大PK 千万级别数据测试结果

    首现创建一张表,然后插入1000+万条数据,接下来进行测试. use TTgoif exists (select * from sysobjects where name='Tonge')drop t ...

随机推荐

  1. PyInstaller编译python3时使用的详细参数介绍

    继续翻译中.... The syntax of the pyinstaller command is: pyinstaller [options] script [script ...] | spec ...

  2. [deviceone开发]-大家比较关注的应用内部升级

    一.简介 这个示例详细介绍了应用内升级的步骤,应用内升级是开发App必须的功能.推荐初学者学习. 二.效果图 三.相关下载 https://github.com/do-project/code4do/ ...

  3. svn服务端和eclipse配合使用

    今天弄了个svn服务器来做项目的版本控制,讲讲我做的步骤吧 1.安装svn服务端 2.下载subclipse插件 3.将subclipse插件安装到eclipse上,点击Install New Sof ...

  4. 深入.net(数据类型)

    C#究竟为我们提供了哪些“数据类型”供我们使用?这些类型有什么样的“特征”? 数据类型的分类: --- 数据类型是存放数据的容器.那么我们就以它们“存放数据的方式”分类! 1.值类型:变量中直接存放着 ...

  5. 【代码笔记】iOS-侧滑效果

    一,效果图. 二,工程图. 三,代码. AppDelegate.h #import <UIKit/UIKit.h> //加入头文件 #import "PPRevealSideVi ...

  6. 荷兰国旗 Flag of the Kingdom of the Netherlands

    问题描述:现有n个红白蓝三种不同颜色的小球,乱序排列在一起,请通过两两交换任意两个球,使得从左至右的球依次为红球.白球.蓝球.这个问题之所以叫做荷兰国旗,是因为将红白蓝三色的小球弄成条状物,并有序排列 ...

  7. MVC中使用SignaIR入门教程

    一.前言:每次写总要说一点最近的感想 进入工作快半年了,昨天是最郁闷的一天,我怀疑我是不是得了"星期一综合征",每个星期一很没有状态.全身都有点酸痛,这个可能一个星期只有周末才打一 ...

  8. mysql下优化表和修复表命令使用说明(REPAIR TABLE和OPTIMIZE TABLE)

    随着mysql的长期使用,可以修复表来优化,优化时减少磁盘占用空间.方便备份. REPAIR TABLE `table_name` 修复表 OPTIMIZE TABLE `table_name` 优化 ...

  9. 判断字符串的首字母 ---------startsWith

    列: {                                            xtype : 'gridcolumn',                                ...

  10. apache 虚拟主机详细配置:http.conf配置详解

    apache 虚拟主机详细配置:http.conf配置详解 Apache的配置文件http.conf参数含义详解 Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd. ...