建造者模式 和 模板模式

=====================================设计模式============================================
C++设计模式——建造者模式

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,
        一类方法是buildPartX(),它们用于创建复杂对象的各个部件;
        另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。
ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象, 
                               也可以提供一个方法返回创建好的复杂产品对象。
Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
Director(指挥者):指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,
        可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。
        客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象,
        然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。

模式总结
===================================================================================================
 先创建具体建造者(包括所有组件的实现)  再创建抽象建造者(拿到具体建造者的实例)  产品角色继承建抽象建造者(自定义实现步骤)
 Director指挥者(拿到抽象建造者的对象,)
 用户需要哪种类型的播放模式,只需要创建一个具体的播放模式,然后把这个播放模式传入到播放器指挥者中就可以了,
 由播放器指挥者处理一系列过程的建造。

播放器
--------------------------------------------------------------------------------------------------
    暴风影音播放器.h头文件代码如下:------------具体建造者
[cpp] view plain copy
<pre name="code" class="cpp">#ifndef _PLAYER_H_  
#define _PLAYER_H_  
#include <iostream>  
#include <string>  
using namespace std;  

//播放器  
class Player  
{  
private:  
    string m_strMenu;           //菜单栏  
    string m_strWindow;         //主窗口  
    string m_strPlayList;           //播放列表  
    string m_strControlBar;         //进度条  
    string m_strCollectList;        //收藏列表  
public:  
    //设置部件  
    void SetMenu(string strMenu);  
    void SetWindow(string strWindow);  
    void SetPlayList(string strPlayList);  
    void SetControlBar(string strControlBar);  
    void SetCollectList(string strCollectList);  

    //获取各部件  
    string GetMenu();  
    string GetWindow();  
    string GetPlayList();  
    string GetControlBar();  
    string GetCollectList();  

    //显示播放器窗口包含的部件  
    void Display();  
};  

#endif  
----------------------------------------------------------------------------
暴风影响播放器Cpp文件代码如下:

[cpp] view plain copy
#include "Player.h"  

//设置主菜单部件  
void Player::SetMenu(string strMenu)  
{  
    m_strMenu = strMenu;  
}  

//设置主窗口部件  
void Player::SetWindow(string strWindow)  
{  
    m_strWindow = strWindow;  
}  

//设计播放列表部件  
void Player::SetPlayList(string strPlayList)  
{  
    m_strPlayList = strPlayList;  
}  

//设置滚动条部件  
void Player::SetControlBar(string strControlBar)  
{  
    m_strControlBar = strControlBar;  
}  

//设置收藏列表部件  
void Player::SetCollectList(string strCollectList)  
{  
    m_strCollectList = strCollectList;  
}  

//获取主菜单部件  
string Player::GetMenu()  
{  
    return m_strMenu;  
}  

//获取主窗口部件  
string Player::GetWindow()  
{  
    return m_strWindow;  
}  

//获取播放列表部件  
string Player::GetPlayList()  
{  
    return m_strPlayList;  
}  

//获取滚动条部件  
string Player::GetControlBar()  
{  
    return m_strControlBar;  
}  


//获取收藏列表部件  
string Player::GetCollectList()  
{  
    return m_strCollectList;  
}  

//显示播放器窗口包含的部件  
void Player::Display()  
{  
    cout << "---" << m_strWindow << endl;  
    cout << "---" << m_strMenu << endl;  
    cout << "---" << m_strPlayList << endl;  
    cout << "---" << m_strControlBar << endl;  
    cout << "---" << m_strCollectList << endl << endl;  
}  

------------------------------------------------------------------------------------------------------


播放模式
--------------------------------------------------------------------------------------------------
 暴风影音播放器能在完整模式、精简模式、记忆模式三种模式下播放,各播放模式下,暴风影音的部件不相同。考虑到扩展性,
 可以定义一个抽象播放模式类,该抽象类中定义了一系列创建具体播放部件的方法。具体的三种播放模式继承于这个抽象播放模式类。


#ifndef _PLAY_PATTERN_H_
#define _PLAY_PATTERN_H_
#include <iostream>
#include <string>
#include "Player.h"
using namespace std;

//抽象播放模式
class PlayPattern
{
protected:
    //具体产品(播放器)
    Player * m_pPlayer;
public:
    PlayPattern()
    {
        m_pPlayer = new Player();
    }

    ~PlayPattern()
    {
        if( NULL != m_pPlayer )
        {
            delete m_pPlayer;

            m_pPlayer = NULL;
        }
    }

    //制造播放窗口
    virtual void BuildWindow() = 0;

    //制造播放菜单
    virtual void BuildMenu() = 0;

    //制造播放列表
    virtual void BuildPlayList() = 0;

    //制造播放进度条
    virtual void BuildControlBar() = 0;

    //制造收藏列表
    virtual void BuildCollectList() = 0;

    //获取产品(播放器)
    Player * GetPlayer()
    {
        return m_pPlayer;
    }
};


//完整播放模式
class FullPattern : public PlayPattern
{
public:
    void BuildWindow();
    void BuildMenu();
    void BuildPlayList();
    void BuildControlBar();
    void BuildCollectList();
};


//精简播放模式
class SimplePattern : public PlayPattern
{
public:
    void BuildWindow();
    void BuildMenu();
    void BuildPlayList();
    void BuildControlBar();
    void BuildCollectList();
};


//记忆播放模式
class MemoryPattern : public PlayPattern
{
public:
    void BuildWindow();
    void BuildMenu();
    void BuildPlayList();
    void BuildControlBar();
    void BuildCollectList();
};

#endif

------------------------------------------------------------------------------------------------------------
播放模式Cpp文件代码如下:

#include "PlayPattern.h"

//制造播放窗口
void FullPattern::BuildWindow()
{
    m_pPlayer->SetWindow("主界面窗口");
}

//制造播放菜单
void FullPattern::BuildMenu()
{
    m_pPlayer->SetMenu("主菜单");
}

//制造播放列表
void FullPattern::BuildPlayList()
{
    m_pPlayer->SetPlayList("播放列表");
}

//制造播放进度条
void FullPattern::BuildControlBar()
{
    m_pPlayer->SetControlBar("进度条");
}

//制造收藏列表
void FullPattern::BuildCollectList()
{
    m_pPlayer->SetCollectList(" ");
}

精简模式///

void SimplePattern::BuildWindow()
{
    m_pPlayer->SetWindow("主界面窗口");
}

void SimplePattern::BuildMenu()
{
    m_pPlayer->SetMenu(" ");
}

void SimplePattern::BuildPlayList()
{
    m_pPlayer->SetPlayList(" ");
}

void SimplePattern::BuildControlBar()
{
    m_pPlayer->SetControlBar("进度条");
}

void SimplePattern::BuildCollectList()
{
    m_pPlayer->SetCollectList(" ");
}

/记忆模式

void MemoryPattern::BuildWindow()
{
    m_pPlayer->SetWindow("主界面窗口");
}

void MemoryPattern::BuildMenu()
{
    m_pPlayer->SetMenu(" ");
}

void MemoryPattern::BuildPlayList()
{
    m_pPlayer->SetPlayList(" ");
}

void MemoryPattern::BuildControlBar()
{
    m_pPlayer->SetControlBar("进度条");
}

void MemoryPattern::BuildCollectList()
{
    m_pPlayer->SetCollectList("收藏列表");
}

------------------------------------------------------------------------------------------------------------------------
2.3 暴风影音播放器指挥者类

 在建造者模式的结构中还引入了一个指挥者类Director,用于控制产品的创建过程。本例中ContructManage就是播放器指挥类。
 用户需要哪种类型的播放模式,只需要创建一个具体的播放模式,然后把这个播放模式传入到播放器指挥者中就可以了,
 由播放器指挥者处理一系列过程的建造。

 ----------------------------------------------------------------------------------------------------------------
 暴风影音播放器指挥者类.h头文件实现如下:
#ifndef _CONTRUCT_MANAGE_H_
#define _CONTRUCT_MANAGE_H_
#include "PlayPattern.h"
#include "Player.h"

//建造管理器
class ContructManage
{
private:
    //具体建造者
    PlayPattern * m_pPlayPattern;
public:
    //设置播放模式
    void SetPlayPattern(PlayPattern * pPlayPattern);

    //封装建造过程
    Player * Construct();
};

#endif
 ----------------------------------------------------------------------------------------------------------------
 暴风影音播放器指挥者类Cpp文件实现如下:

#include "ContructManage.h"

//设置播放模式
void ContructManage::SetPlayPattern(PlayPattern * pPlayPattern)
{
    m_pPlayPattern = pPlayPattern;
}

//封装建造过程
Player * ContructManage::Construct()
{
    m_pPlayPattern->BuildWindow();
    m_pPlayPattern->BuildMenu();
    m_pPlayPattern->BuildPlayList();
    m_pPlayPattern->BuildControlBar();
    m_pPlayPattern->BuildCollectList();

    Player * pPlayer = m_pPlayPattern->GetPlayer();
    return pPlayer;
}
----------------------------------------------------------------------------------------------------------------
============================================================================================================
#include <iostream>
#include "ContructManage.h"
#include "PlayPattern.h"
#include "Player.h"
using namespace std;

int main()
{
        /***********************创建建造管理器**********************/
    ContructManage * pContructManage = new ContructManage();
    Player * pPlayer = NULL;

    /***********************完整播放模式************************/
    PlayPattern * pFullPattern = new FullPattern();
    cout << "完整播放模式:" << endl;
    pContructManage->SetPlayPattern(pFullPattern);
    pPlayer = pContructManage->Construct();
    pPlayer->Display();

    /***********************精简播放模式************************/
    PlayPattern * pSimplePattern = new SimplePattern();
    cout << "精简播放模式:" << endl;
    pContructManage->SetPlayPattern(pSimplePattern);
    pPlayer = pContructManage->Construct();
    pPlayer->Display();

    /***********************记忆播放模式************************/
    PlayPattern * pMemoryPattern = new MemoryPattern();
    cout << "记忆播放模式:" << endl;
    pContructManage->SetPlayPattern(pMemoryPattern);
    pPlayer = pContructManage->Construct();
    pPlayer->Display();

    /***********************销毁操作****************************/
    cout << endl;
    delete pFullPattern;
    pFullPattern = NULL;

    delete pSimplePattern;
    pSimplePattern = NULL;

    delete pMemoryPattern;
    pMemoryPattern = NULL;

    delete pContructManage;
    pContructManage = NULL;

    return 0; 
]


5.1.主要优点

    建造者模式的主要优点如下:

    (1) 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,
        使得相同的创建过程可以创建不同的产品对象。建造者模式封装了产品具体的创建流程,符合"封装变化原则"。

    (2) 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,
       用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有类库的代码,
       统扩展方便,符合“开闭原则”,也符合"针对抽象进行编程而不是针对具体编程原则"。

    (3) 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,
       也更方便使用程序来控制创建过程。

5.2.主要缺点

    建造者模式的主要缺点如下:

    (1) 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,
        例如很多组成部分都不相同,不适合使用建造者模式,因此其使用范围受到一定的限制。

    (2) 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

3.建造者模式的具体应用

    (1)在游戏角色中,存在魔鬼、天使、英雄等角色。这些角色都包含相同的建造过程(建造头、脚、外观等),
    而每一个游戏角色建造方法各不相同。

    (2)解析XML格式的配置文件时,需要解析配置文件的头部信息、数据体、尾部信息等。可以把解析的三个过程视为建造的三个过程。

    (3)解析Rtf文档格式同样存在和解析XML格式的配置文件相同的情况。

    (4)我们使用Email发送邮件的是否,需要填写邮件标题、收件人、邮件内容等信息。可以把填写邮件标题、收件人、
    邮件内容视为三个建造过程。

    (5)我们在定义Socket网络通信协议的时候,需要定义数据祯,每祯由包头、包体、包尾组成。这样在通信的双方,
    就可以按照同样的格式进行收发信息。

    (6)使用Gcc编译程序需要经历编译、汇编、链接等过程,最终才能形成可执行程序。

    (7)我们使用美图、Photoshop软件美化图像时,得执行一系列操作(锐化、镜像等),最终才有一副绚丽的照片。

    (8)在创建对话框程序过程中,会有一个向导提示每一步的创建过程。经历一系列的过程,最终才形成一个对话框。
    同样,在安装软件的过程中,也会出现向导让我们定制软件的某些外观或者功能。

    (9)在定制Linux内核过程中,可以根据需要删减某些不需要的功能模块。定制出一个功能适中的操作系统,俗称内核裁剪,
    然后把裁剪后的Linux系统移植到嵌入式设备上(ARM等)。

    (10)生活中的建造者模式应用: 桥梁建造、三峡工程建造、鸟巢水立方等一系列工程建造;361、安踏、九牧王一系列服装业建造;
    杂交水稻、转基因大米等粮食建造。


-------------------------------------------------------------------------------------------------------------------------
C++设计模式——模版方法
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。
模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤


----------------------------------------------------------------------------------------------------------------------------
#ifndef _DECRYPT_H_
#define _DECRYPT_H_

#include <iostream>
#include <string>
using namespace std;


//接收到的短消息
class ShortMsg
{
public:
    //基本方法: 接收编码后的消息
    void RecvMsg()
    {
        cout << "接收编码后的: <发送人> 字段内容" << endl;
        cout << "接收编码后的: <消息长度> 字段内容" << endl;
        cout << "接收编码后的: <数据内容> 字段内容" << endl;
        cout << "------------------------------------------" << endl << endl;
    }

    //基本方法: 译码消息
    virtual void DecryptMsg() = 0;

    //基本方法: 显示译码后的消息
    void DisplayMsg()
    {
        cout << "显示译码后的: <发送人> 字段内容" << endl;
        cout << "显示译码后的: <消息长度> 字段内容" << endl;
        cout << "显示译码后的: <数据内容> 字段内容" << endl;
        cout << "------------------------------------------" << endl << endl;
    }

    //模板方法: 执行译码操作
    void ExcuteDecrypt()
    {
        RecvMsg();
        DecryptMsg();
        DisplayMsg();
    }
};


//7转8译码
class SevenTo8Decrypt : public ShortMsg
{
public:
    //7转8译码
    void DecryptMsg()
    {
        cout << "对编码后的: <发送人> 字段内容进行7转8译码" << endl;
        cout << "对编码后的: <消息长度> 字段内容进行7转8译码" << endl;
        cout << "对编码后的: <数据内容> 字段内容进行7转8译码" << endl;
        cout << "------------------------------------------" << endl << endl;
    }
};



//8转7译码
class EightTo7Decrypt : public ShortMsg
{
public:
    //8转7译码
    void DecryptMsg()
    {
        cout << "对编码后的: <发送人> 字段内容进行8转7译码" << endl;
        cout << "对编码后的: <消息长度> 字段内容进行8转7译码" << endl;
        cout << "对编码后的: <数据内容> 字段内容进行8转7译码" << endl;
        cout << "------------------------------------------" << endl << endl;
    }
};


#endif
-----------------------------------------------------------------------------------------------------------------------

#include <iostream>
#include "Decrypt.h"
using namespace std;

int main()
{
    //对接收到的消息进行7转8译码
    ShortMsg * p7To8Decrypt = new SevenTo8Decrypt();
    p7To8Decrypt->ExcuteDecrypt();

    delete p7To8Decrypt;

    return 0;
}
-----------------------------------------------------------------------------------------------------------------------

3、模板方法模式总结

    模板方法模式是基于继承的代码复用技术,将公共的方法(一般都是不变的部分)封装到父类中,而可变的部分可以通过继承来继续扩展,
    把变化部分和不变化部分分隔开。一方面能够实现代码复用,另一方面便于维护,它体现了面向对象的诸多重要思想,
    如封装变化思想"找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。换句话说,
    如果每次新的需求一来,都会使某些方面的代码发生变化,那么可以确定,这部分的代码需要被抽象出来,和其他稳定的代码有所区别"。
    模板方法把一些基本方法按照一定的顺序组合起来,实现某个功能。如果不使用模板方法把这些基本方法按照一定的顺序给组合起来,
    则子类可以使用任意的顺序组合这些基本方法,导致程序逻辑混乱,无法控制。模式广泛应用于框架设计中,
    以确保通过父类来控制处理流程的逻辑顺序。


1.模板方法模式的主要优点

    (1) 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。

    (2) 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中(不变的部分),
         而通过其子类来实现不同的行为(异变部分),它鼓励我们恰当使用继承来实现代码复用。

    (3) 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。

    (4) 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,
        符合单一职责原则和开闭原则。

2.模板方法模式的主要缺点

    (1)需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,
       设计也更加抽象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值