`
mmdev
  • 浏览: 12929163 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

【设计模式】商场促销 -- 策略模式

 
阅读更多

一,概念

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

二,策略模式的组成

   1)抽象策略角色: 策略类,通常由一个接口或者抽象类实现。
   2)具体策略角色:包装了相关的算法和行为。

   3)环境角色:持有一个策略类的引用,最终给客户端调用。

三,补充C++知识

类对象的构造顺序是这样的:
1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员
2.进入构造函数后在构造函数中执行一般计算
1)类里面的任何成员变量在定义时是不能初始化的。
2)一般的数据成员可以在构造函数中初始化。
3)const数据成员必须在构造函数的初始化列表中初始化。
4)static要在类的定义外面初始化。
5)数组成员是不能在初始化列表里初始化的。
6)不能给数组指定明显的初始化。
这6条一起,说明了一个问题:C++里面是不能定义常量数组的!因为3和5的矛盾。这个事情似乎说不过去啊?没有办法,我只好转而求助于静态数据成员。
到此,我的问题解决。但是我还想趁机复习一下C++类的初始化:
1.初始化列表:CSomeClass::CSomeClass() : x(0), y(1){}
2.类外初始化:int CSomeClass::myVar=3;
3.const常量定义必须初始化,C++类里面使用初始化列表;
4.C++类不能定义常量数组。

在C++类中,必须做如下事情:

1.必须对任何const或引用类型成员以及没有默认构造函数的 类 类型 的任何成员 显示地使用初始化列表进行初始化

2.类成员在定义时是不能被初始化的

3.类的成员初始化顺序与成员变量在构造函数中的位置选后顺序无关,至于成员变量在类中定义的先后顺序有关

C++默认继承方式为private

C++ new 生成的对象为指针,所以new 前面的对象要声明为指针类型

四,实例

计算器简单工厂模式的精简实现

#include <iostream>
using namespace std;

class COperation//基类
{
public:
	int m_nFirst;
	int m_nSecond;
	virtual double GetResult()
	{
		double dResult=0;
		return dResult;
	}
};

class AddOperation : public COperation//加法
{
public:
	virtual double GetResult()
	{
		return m_nFirst+m_nSecond;
	}
};

class SubOperation : public COperation//减法
{
public:
	virtual double GetResult()
	{
		return m_nFirst-m_nSecond;
	}
};


class CCalculatorFactory//工厂类
{
    
public://静态方法属于类本身,不属于哪个对象 
	static COperation* Create(char cOperator);

};

COperation* CCalculatorFactory::Create(char cOperator)//工厂类的实现
{
	COperation *oper;
	
    //在C#中可以用反射来取消判断时用的switch,在C++中用什么呢?RTTI??
	switch (cOperator)
	{
		case '+':
			oper=new AddOperation();
		     break;
		case '-':
			oper=new SubOperation();
            break;
		default:
			oper=new AddOperation();
	     	break;
	}
	return oper;
}

int main()
{
	int a,b;
	cin>>a>>b;
	
	/*静态方法为类所有,可以通过对象来使用,也可以通过类来使用。
	但一般提倡通过类名来使用,因为静态方法只要定义了类,不必建立类的实例就可使用*/
	COperation * op = CCalculatorFactory::Create('-');//静态方法调用方式 
	op->m_nFirst=a;
	op->m_nSecond=b;
	cout<<op->GetResult()<<endl;
	return 0;
}

将简单工厂模式优化为策略模式后的代码如下:

#include <iostream>
using namespace std; 

//策略基类
class COperation
{
public:
	int m_nFirst;
	int m_nSecond;
	virtual double GetResult()
	{
		double dResult=0;
		return dResult;
	}
};

//策略具体类-加法类
class AddOperation : public COperation
{
public:
	AddOperation(int a,int b)
	{
		m_nFirst=a;
		m_nSecond=b;
	}
	virtual double GetResult()
	{
		return m_nFirst+m_nSecond;
	}
};

class Context//策略类 
{
private:
	COperation* op;
public:
    Context(COperation* temp)//参数为策略基类(传递的时候被初始化为子类) 
	{
        op=temp;
	}
	double GetResult()
	{
		return op->GetResult();
	}
};

//客户端
int main()
{
	int a,b;
    char c;
	cin>>a>>b;
    cout<<"请输入运算符:";
    cin>>c;
    switch(c)
    {
       case '+':
	        Context *context=new Context(new AddOperation(a,b));
     	     cout<<context->GetResult()<<endl;
            break;
       default:
            break;
    }
	return 0;
}

这里将策略(操作符)封装成一个Context类,通过传递操作符子对象来返回相应子对象下操作结果。

菜鸟实现工厂模式和策略模式

客户端只需访问Context类,而不用知道其它任何类信息,实现了低耦合。在上例基础上,修改下面内容

#include <iostream>
using namespace std;
 
 
 //策略基类
class COperation
{
public:
	int m_nFirst;
	int m_nSecond;
	virtual double GetResult()
	{
		double dResult=0;
		return dResult;
	}
};

//策略具体类-加法类
class AddOperation : public COperation
{
public:
	AddOperation(int a,int b)
	{
		m_nFirst=a;
		m_nSecond=b;
	}
	AddOperation()
	{
		m_nFirst=0;
		m_nSecond=0;
	}
	virtual double GetResult()
	{
		return m_nFirst+m_nSecond;
	}
};
class Context
{
private:
	COperation* op;
public:
    Context(char cType)
	{
        switch (cType)
        {
		case '+':
			op=new AddOperation(3,8);
			break;
		default:
			op=new AddOperation();
			break;
        }
	}
	double GetResult()
	{
		return op->GetResult();
	}
};
//客户端
int main()
{
	Context *test=new Context('+');
	cout<<test->GetResult()<<endl;
	return 0;
}

五,商场促销例子

这里想说的是,abstract 关键字是微软为C#定义的,抽象类关键字。C++中没有抽象类,如果想成为抽象类在类中定义纯虚函数就可以了。只要拥有纯虚函数的类就是抽象类,由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

商场促销的简单工厂实现:

#include <iostream>

using namespace std;

class CashSuper //现金收费抽象类
{
public:
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! (不能只定义,而不实现)
    {
        
    }
};

class CashNormal : public CashSuper //收费子类,正常收费
{
public:
     double acceptCash(double money)
     {
         return money;
     }
    
};

class CashRebate : public CashSuper //打折收费子类
{
private:
    double moneyRebate;//不允许初始化
public:
    CashRebate(double moneyRebate)
    {
        this->moneyRebate=moneyRebate;
    }
    double acceptCash(double money)
    {
         return money*moneyRebate;
    }
};

class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)
{
private:
    double moneyCondition ;//返利购买额度
    double moneyReturn ;//返利多少
public:
    CashReturn(double moneyCondition,double moneyReturn)
    {
        this->moneyCondition=moneyCondition;
        this->moneyReturn=moneyReturn;
    }
    double acceptCash(double money)
    {
        double result = money;
        if(money >= moneyCondition )
            result = money-(money/moneyCondition)*moneyReturn;
        return result;
        
    }
};

class CashFactory
{
public:
    static CashSuper* creatCashAccept(string type)//根据子类type来生成相应收费子类
    {
        CashSuper *cs;
        if(type=="CashNormal")
            cs=new CashNormal();
        else if(type == "CashRebate")
            cs=new CashRebate(0.8);
        else if(type == "CashReturn")
            cs=new CashReturn(300,100);
        
        return cs;
    }
};

int main(int argc, char** argv) {

    CashSuper *csuper = CashFactory::creatCashAccept("CashRebate");
    double result=csuper->acceptCash(500);//500打八折,应该输出 400
    cout<<"CashRebate 500 is:"<<result<<endl;
    return 0;
}

  策略模式:定义了算法家族,分别封装起来,让它们之间可以相互替换,算法的变化不会影响使用算法的客户。
主要升级就是,将算法封装到Context中,然后通过传递对象生成相应子类对象,然后得到结果。

#include <iostream>

using namespace std;

class CashSuper //现金收费抽象类
{
public:
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! 
    {
        
    }
};

class CashNormal : public CashSuper //收费子类,正常收费
{
public:
     double acceptCash(double money)
     {
         return money;
     }
    
};

class CashRebate : public CashSuper //打折收费子类
{
private:
    double moneyRebate;//不允许初始化
public:
    CashRebate(double moneyRebate)
    {
        this->moneyRebate=moneyRebate;
    }
    double acceptCash(double money)
    {
         return money*moneyRebate;
    }
};

class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)
{
private:
    double moneyCondition ;//返利购买额度
    double moneyReturn ;//返利多少
public:
    CashReturn(double moneyCondition,double moneyReturn)
    {
        this->moneyCondition=moneyCondition;
        this->moneyReturn=moneyReturn;
    }
    double acceptCash(double money)
    {
        double result = money;
        if(money >= moneyCondition )
            result = money-(money/moneyCondition)*moneyReturn;
        return result;
        
    }
};

/*class CashFactory
{
public:
    static CashSuper* creatCashAccept(string type)//根据子类type来生成相应收费子类
    {
        CashSuper *cs;
        if(type=="CashNormal")
            cs=new CashNormal();
        else if(type == "CashRebate")
            cs=new CashRebate(0.8);
        else if(type == "CashReturn")
            cs=new CashReturn(300,100);
        
        return cs;
    }
};*/

class CashContext
{
private:
    CashSuper cs;
public:
    CashContext(CashSuper csuper)
    {
        this->cs=csuper;
    }
    double GetResult(double money)
    {
        return cs.acceptCash(money);
    }
};

int main(int argc, char** argv) {

    //CashSuper *csuper = CashFactory::creatCashAccept("CashRebate");
    //double result=csuper->acceptCash(500);//500打八折,应该输出 400
    
    
     CashContext *cs;
     string type="CashRebate";
     
     if(type=="CashNormal")
            cs=CashContext(new CashNormal());
     else if(type == "CashRebate")
            cs=CashContext(new CashRebate(0.8));
     else if(type == "CashReturn")
            cs=CashContext(new CashReturn(300,100));
        
        
    cout<<"CashRebate 500 is"<<cs->GetResult(500)<<endl;
    return 0;
}


这样仍然存在缺点:就是让客户端来判断生成哪个子类。

改进策略是,让策略模式和工厂模式结合

#include <iostream>

using namespace std;

class CashSuper //现金收费抽象类
{
public:
    virtual double acceptCash(double money)//不能设置为纯虚函数,后面还要生成对象用呢!!!! 
    {
        
    }
};

class CashNormal : public CashSuper //收费子类,正常收费
{
public:
     double acceptCash(double money)
     {
         return money;
     }
    
};

class CashRebate : public CashSuper //打折收费子类
{
private:
    double moneyRebate;//不允许初始化
public:
    CashRebate(double moneyRebate)
    {
        this->moneyRebate=moneyRebate;
    }
    double acceptCash(double money)
    {
         return money*moneyRebate;
    }
};

class CashReturn :public CashSuper //返利收费子类(默认继承为私有继承)
{
private:
    double moneyCondition ;//返利购买额度
    double moneyReturn ;//返利多少
public:
    CashReturn(double moneyCondition,double moneyReturn)
    {
        this->moneyCondition=moneyCondition;
        this->moneyReturn=moneyReturn;
    }
    double acceptCash(double money)
    {
        double result = money;
        if(money >= moneyCondition )
            result = money-(money/moneyCondition)*moneyReturn;
        return result;
        
    }
};

/*class CashFactory
{
public:
    static CashSuper* creatCashAccept(string type)//根据子类type来生成相应收费子类
    {
        CashSuper *cs;
        if(type=="CashNormal")
            cs=new CashNormal();
        else if(type == "CashRebate")
            cs=new CashRebate(0.8);
        else if(type == "CashReturn")
            cs=new CashReturn(300,100);
        
        return cs;
    }
};*/

class CashContext
{
private:
    CashSuper cs;
public:
    CashContext(string type)
    {
        if(type=="CashNormal")
            this->cs=new CashNormal();
        else if(type == "CashRebate")
            this->cs=new CashRebate(0.8);
        else if(type == "CashReturn")
            this->cs=new CashReturn(300,100);
              
    }
    double GetResult(double money)
    {
        return cs.acceptCash(money);
    }
};

int main(int argc, char** argv) {

     CashContext *cs=new CashContext("CashRebate");
           
     cout<<"CashRebate 500 is"<<cs->GetResult(500)<<endl;
    return 0;
}


这样客户端只需要更改金额和打折手段就可以了。相对简单工厂的提升为:简单工厂需要让客户调用两个类SuperCash和CashFactory。而结合之后仅仅需要调用CashContext就可以了

相对与策略模式的提升为:客户端需要承担的判断更少了,更简洁了


分享到:
评论

相关推荐

    策略模式--商场促销_设计模式.rar

    面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和...策略模式:它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户

    java设计模式-策略模式

    此代码简单的模拟了超市的促销策略,有打折、返钱等操作!针对商场中出现的各种各样的促销策略,很方便的便可实现策略的拓展!

    设计模式一(单子、工厂、策略模式)练习 .zip

    设计模式一(单子、工厂、策略模式)练习 1. 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本 7%的促销折扣;而对非教材类的计算 机...

    C#策略模式典型演示程序源代码

    摘要:C#源码,菜单窗体,策略模式,设计模式 商场促销-策略模式-大话设计模式,策略模式典型演示程序C#源代码,演示程序很好的解释了策略模式的编程模板。源码中包括:现金收费抽象类(现金收取超类的抽象方法,收取...

    北邮java李劼java大作业,设计模式二

    1. 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣;...使用策略模式、工厂模式、单子模式进行设计,类图如下。

    北邮Java大作业低配版

    设计模式一(单子、工厂、策略模式)练习 1. 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣;而对非教材类的计算机图书...

    北邮java选修大作业 购物车

    大作业设计模式一(单子、工厂、策略模式)练习 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣;而对非教材类的计算机...

    创建性设计模式1

    背景某商场节假日有固定促销活动,为了加大促销力度,现提升国庆节促销活动规格;要点策略模式提供了一系列可重用的算法,从而可以使得类型在运时方便地根据需要在各个算法

    甘孜州文化旅游产品市场营销策略研究-kaic.doc

    本人原创毕业设计,未抄袭他人,请人工审核,如出现版权问题,个人承担责任,感谢! 目 录 一、绪论 (一)背景 (二)研究目的及意义 1.研究目的 2.研究意义 (三)国内外文化旅游产品营销策略研究现状 (四)研究...

    自有仓模式基础上进行电商订单集中处理系统.docx

    为解决上述问题并建立灵活高效的电商处理机制,该公司决定在应用自有仓模式基础上进行电商订单集中处理系统的设计实现工作。 系统开发工作应用B/S架构、JFinal框架、SQL Server 2016数据库等技术,B/S架构和J2EE平台...

    购物车系统——Java大作业.zip

    单子、工厂、策略、组合、观察者模式 ...使用策略模式、工厂模式、单子模式进行设计,类图如下。 在设计模式一的作业基础上,设计一个贩卖各类书籍的电子商务网站的购物车系统。该系统包括的模块有:

    汽车新媒体:结合场景设计好传播模式并降低成本.pptx

    运营者需要设计促销策略,并用海报、文章等内容形式触达用户,以期获得更好的销售反馈。;帮助企业增加互联网话题内容,企业的新媒体传播能力会随着产品交付而升级。;现阶段对于铺天盖地的互联网广告“轰炸”,网民更...

    php 网上商城促销设计实例代码

    前一篇文章讲的是购物车的设计,这篇来讲下关于促销的。支持的促销类似于,打折,买几赠几,满多少钱送礼品等等。用到策略模式

    商业计划书-方案设计(包含word和ppt)

    经济模型:根据公司的商业模式和运作方式,设计出完整的经济模型,包括收入来源、成本结构和利润预期等。 财务规划:根据经济模型,制定财务规划和预算,并展示投资回报率(ROI)和投资回收期(IRR)等指标。 团队...

    使用客户轨迹模式的移动定位-研究论文

    为了分析这种新策略的有效性,我们在 2014 年 6 月的 14 天内在大型购物中心设计了一项大规模随机现场实验,涉及 83,370 个唯一用户响应。我们发现基于轨迹的移动定位可以导致与其他基线相比,更高的赎回概率、更快...

    ECSHOP 通用电子商务平台

    7、代码的开源和免费的发展策略 我们认为开源是一个趋势,同时也是一个商业模式。我们也同样认为免费是一个趋势,同时也是一个商业模式。 我们不是说我们不想收费,而是希望在用户能够在提高自身收入和价值的同时...

    电子商务创业方案设计.doc

    可以通过发传单来宣传我们的产品,吸引人们的注意力c渠道策 略,我们店铺采用的是直销的方式d产品策略,为了使我们的产品在消费者心目中留下深 刻的印象,我们采取了比较时尚个性的鞋子图案e促销策略,在换季、节...

    创青春获奖-生物医学类

    经济模型:根据公司的商业模式和运作方式,设计出完整的经济模型,包括收入来源、成本结构和利润预期等。 财务规划:根据经济模型,制定财务规划和预算,并展示投资回报率(ROI)和投资回收期(IRR)等指标。 团队...

    商业计划书PPT-演示文稿

    经济模型:根据公司的商业模式和运作方式,设计出完整的经济模型,包括收入来源、成本结构和利润预期等。 财务规划:根据经济模型,制定财务规划和预算,并展示投资回报率(ROI)和投资回收期(IRR)等指标。 团队...

Global site tag (gtag.js) - Google Analytics