【5】设计模式之Prototype模式

本文探讨了电子账单系统中的广告信模块开发流程,包括使用原型模式实现模版化邮件生成,以及如何确保个性化服务和邮件送达率。通过类图展示了关键类及其接口,详细解释了如何通过原型模式克隆邮件模板,生成个性化广告信并高效发送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、描述

Prototype模式提供了自我复制的功能,新对象的创建可以通过已有对象进程创建,Prototype通过提供一个已存在对象进行新对象创建的借口Clone()。

2、示例

现在电子账单越来越流行了,比如你的信用卡,到月初的时候银行就会发一份电子邮件到你邮箱中,说你这个月消费了多少,什么时候消费的,积分是多少等等,这个是每个月发一次,但是还有一种也是银行发的邮件你肯定有印象:广告信,现在各大银行的信用卡部门都在拉拢客户,电子邮件是一种廉价、快捷的通讯方式,你用纸质的广告信那个费用多高呀,比如我今天推出一个信用卡刷卡抽奖活动,通过电子账单系统可以一个晚上发送给 600 万客户,为什么要用电子账单系统呢?直接找个发垃圾邮件不就解决问题了吗?是个好主意,但是这个方案在金融行业是行不通的,银行发这种邮件是有要求的,一是一般银行都要求个性化服务,发过去的邮件上总有一些个人信息吧,比如“XX 先生”,“XX 女士”等等,二是邮件的到达率有一定的要求,由于大批量的发送邮件会被接收方邮件服务器误认是垃圾邮件,因此在邮件头要增加一些伪造数据,以规避被反垃圾邮件引擎误认为是垃圾邮件;从这两方面考虑广告信的发送也是电子账单系统(电子账单系统一般包括:账单分析、账单生成器、广告信管理、发送队列管理、发送机、退信处理、报表管理等)的一个子功能,我们今天就来考虑一下广告信这个模块是怎么开发的。那既然是广告信,肯定需要一个模版,然后再从数据库中把客户的信息一个一个的取出,放到模版中生成一份完整的邮件,然后扔给发送机进行发送处理,我们来看类图:

 

工程目录:


AdvTemplate

//AdvTemplate.h
#ifndef __Prototype__AdvTemplate__
#define __Prototype__AdvTemplate__
#include <iostream>
using std::string;
class CAdvTemplate
{
public:
CAdvTemplate();
~CAdvTemplate();
string GetAdvSubject();
string GetAdvContext();
private:
string m_advSubject;
string m_advContext;
};
#endif /* defined(__Prototype__AdvTemplate__) */
//AdvTemplate.cpp
#include "AdvTemplate.h"
CAdvTemplate::CAdvTemplate()
{
this->m_advSubject = "XX银行国庆信用卡抽奖活动";
this->m_advContext = "国庆抽奖活动通知:只要刷卡就送你1百万!……";
}
CAdvTemplate::~CAdvTemplate(void)
{
}
//取得广告信的名称
string CAdvTemplate::GetAdvSubject()
{
return this->m_advSubject;
}
//取得广告信的名称
string CAdvTemplate::GetAdvContext()
{
return this->m_advContext;
}

Mail

//Mail.h
#ifndef __Prototype__Mail__
#define __Prototype__Mail__

#include <iostream>
#include "ICloneableNow.h"
#include "AdvTemplate.h"

using std::string;

class CMail : public ICloneableNow
{
public:
    CMail(CAdvTemplate* pAdvTemp);
    ~CMail();
    string getReceiver();
    void setReceiver(string& receiver);
    string getSubject();
    void setSubject(string& subject);
    string getAppellation();
    void setAppellation(string& appellation);
    string getContxt();
    void setContxt(string& contxt);
    string getTail();
    void setTail(string& tail);
    CMail * Clone();
    
private:
    string m_receiver;    //收件人
    string m_subject;     //邮件名称
    string m_appellation; //称谓
    string m_contxt;      //邮件内容
    string m_tail;        //邮件的尾部,一般都是加上“XXX版权所有”等信息
};

#endif /* defined(__Prototype__Mail__) */

//Mail.cpp
#include "Mail.h"

CMail::CMail(CAdvTemplate* pAdvTemp)
{
    m_contxt = pAdvTemp->GetAdvContext();
    m_subject = pAdvTemp->GetAdvSubject();
}

CMail::~CMail()
{
    
}
string CMail::getReceiver()
{
    return m_receiver;
}

void CMail::setReceiver(string& receiver)
{
    m_receiver = receiver;
}

string CMail::getSubject()
{
    return m_subject;
}

void CMail::setSubject(string& subject)
{
    m_subject = subject;
}

string CMail::getAppellation()
{
    return m_appellation;
}

void CMail::setAppellation(string& appellation)
{
    m_appellation = appellation;
}

string CMail::getContxt()
{
    return m_contxt;
}

void CMail::setContxt(string& contxt)
{
    m_contxt = contxt;
}

string CMail::getTail()
{
    return m_tail;
}

void CMail::setTail(string& tail)
{
    m_tail = tail;
}

CMail* CMail::Clone()
{
    const CMail entity = *this;
    CMail* pMail = new CMail(entity);
    return pMail;
}
ICloneableNow:增加该接口同时在Mail中重写Clone方法,避免sendMail修改为多线程后存在安全性问题

#ifndef Prototype_ICloneableNow_h
#define Prototype_ICloneableNow_h
class CMail;
class ICloneableNow
{
public:
    
    ICloneableNow(void)
    {
    }
    
    virtual ~ICloneableNow(void)
    {
    }
    virtual CMail * Clone() = 0;
};

#endif
main.cpp

#include <iostream>
#include "Mail.h"
#include "AdvTemplate.h"
#include <time.h>
using std::cout;
using std::endl;
using std::string;

int rand_int(int min,int max)
{
    int temp = rand()%max;
    while(temp < rand()%min)
        temp = rand()%max;
    return temp;
}

int getRand1()
{
    srand((unsigned int)time(0));
    for(int i = 0; i <= 9; i++)
    {
        int temp = rand();
        cout << temp << endl;
        return temp;
    }
    return 0;
}

int gerRand2(int previout)
{
    srand((unsigned int)time(NULL)+ previout);
    for(int i = 0; i < 100; i++)
    {
        int j = rand()%52;
        if(j != previout)
            return j;
    }
    return 0;
}

char *pSource = "0abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string getRandString(int count)
{
    char* pRet = new char[count + 1];
    int index = static_cast<int>(time(NULL));
    for(int i = 0; i < count; i++)
    {
        index = rand_int(5, 30);
        pRet[i] = *(pSource + index);
    }
    pRet[count] = '\0';
    string ret(pRet);
    delete pRet;
    pRet = NULL;
    return ret;
}

void sendMail(CMail mail)
{
    cout << " 主题:" << mail.getSubject().c_str();
    cout << " 收件人:" << mail.getReceiver().c_str();
    cout << " ....邮件发送成功" << endl;
}

void DoIt()
{
    int i = 0;
    int count = 3;
    CAdvTemplate temp;
    CMail mail(&temp);
    string tail("XX银行版权所有");
    mail.setTail(tail);
    while(i < count)
    {
        CMail* pCloneMail = mail.Clone();
        string appellation = getRandString(8);
        appellation.append("先生(女士)");
        pCloneMail->setAppellation(appellation);
        string receiver = getRandString(5);
        receiver.append("@");
        receiver.append(getRandString(8));
        receiver.append(".com");
        
        pCloneMail->setReceiver(receiver);
        sendMail(*pCloneMail);
        delete pCloneMail;
        i++;
    }
}
int main(int argc, const char * argv[]) {
    // insert code here...
    DoIt();
    std::cout << "Hello, World!\n";
    return 0;
}

3、运行结果



参考资料:http://blog.youkuaiyun.com/rexuefengye/article/details/12704821,感谢 热血枫叶 博主的精彩博文。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值