第二章 商品促销-策略模式(读书笔记)

第二章 商品促销-策略模式(读书笔记) 

1.面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
2.打一折和九折只是形式的不同,抽象分析出来,所有的打折算法都是一样的。所有每一种打折建一个类是非常不合适的。
3.简单工厂模式只是解决对象的创建问题,如果在商品促销系统中,经常性地改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂。所有在这个商品促销的系统中简单工厂模式并不是很适用。
4.策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
5.算法本身只是一种策略,最重要的是算法如果是随时都可能互相替换的,这就是变化点。
6.简单工厂模式需要让客户端认识两个类,CashSuper和CashFactory,而策略模式与简单工厂结合的用法,客户端就只需要认识一个类CashContext就可以了,耦合更加降低了。(参照2.6)
7.策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
8.策略模式中的Context中封装了变化。选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。这样就最大化地减轻了客户端的职责。
9.策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

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

2.1商场收银软件的MFC版,先看看简单的界面

程序2.1 最简单的功能就在这两个按钮里面

void CDesignPartern21Dlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	UINT valA = GetDlgItemInt(IDC_EDIT1, NULL, FALSE);
	UINT valB = GetDlgItemInt(IDC_EDIT2, NULL, FALSE);
	SetDlgItemInt(IDC_EDIT3,valA * valB,FALSE);
	//OnOK();
}
void CDesignPartern21Dlg::OnBnClickedCancel()
{
	// TODO: 在此添加控件通知处理程序代码
	SetDlgItemInt(IDC_EDIT1 ,0,FALSE);
	SetDlgItemInt(IDC_EDIT2 ,0,FALSE);
	SetDlgItemInt(IDC_EDIT3 ,0,FALSE);
	//OnCancel();
}

 

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

程序2.3 商品促销软件的简单工厂实现

2.3.1 首先是现金类CashSuper.h

#pragma once 

class CashSuper
{
public:
	virtual double AcceptCash(double money) = 0;
};

class CashNormal :public CashSuper
{
public:
	//正常收费,按原价返回
	double AcceptCash(double money)
	{
		return money;
	};
};

class CashRebate :public CashSuper
{
public:
	CashRebate(double rebate)
		:m_moneyRebate(1.0)
	{
		m_moneyRebate = rebate;
	}
	//打折后返回
	double AcceptCash(double money)
	{
		return money * m_moneyRebate;
	};
private:
	double m_moneyRebate;
};

class CashReturn :public CashSuper
{
public:
	CashReturn(double returnMoney,double condition)
		:m_moneyReturn(0.0)
		,m_moneyCondition(0.0)
	{
		m_moneyReturn = returnMoney;
		m_moneyCondition = condition;
	}

	double AcceptCash(double money)
	{
		double resultMoney = money;
		if (money > m_moneyCondition)
		{//减去返利值
			resultMoney = money - (money / m_moneyCondition )* m_moneyReturn;
		}
		return resultMoney;
	};
private:
	//返回现金
	double m_moneyReturn;
	//返利条件
	double m_moneyCondition;
};


2.3.2 简单工厂类

#pragma once
#include "CashSuper.h"
typedef enum _Type
{
	eNormal = 0,//正常收费
	e80Discount,
	e70Discount,
	e50Discount,
	eReturn		//满300减100
}MyDiscount;

class CashFactory
{
public:
	static CashSuper* CreateCashAccept(MyDiscount type)
	{
		CashSuper* cs = NULL;
		switch (type)
		{
		case eNormal:
			cs = new CashNormal();
			break;
		case e80Discount:
			cs = new CashRebate(0.8);
			break;
		case e70Discount:
			cs = new CashRebate(0.7);
			break;
		case e50Discount:
			cs = new CashRebate(0.5);
			break;
		case eReturn:
			cs = new CashReturn(100,300);
			break;
		default:
			cs = new CashNormal();
			break;
		}
		return cs;
	};
};


2.3.3 客户端的调用

#include "stdafx.h"
#include "CashFactory.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
 double Price;
 double Num;
 int selectedIndex;
 //Price
 cout << "please Input you Price: " << endl;
 cin >> Price;
 //Num
 cout << "please Input you Num: " << endl;
 cin >> Num;
 //Discount
 cout << "please Input you Discount: " 
  << "0:正常收费, 1:8折, 2:7折, 3:5折, 4:满300减100" << endl;
 cin >> selectedIndex;

 CashSuper* cash = CashFactory::CreateCashAccept((MyDiscount)selectedIndex);
 
 cout << "The total Price is "<< cash->AcceptCash(Price * Num) << endl;
 return 0;
}


 2.3.4 最后实现的UML就是和下面这个图一样

 

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

2.4 在我们用策略模式之前,先看看策略模式的图,比较一下就知道它和简单工厂模式的不同了。

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

2.5 看看这个商品促销系统是如何用上这个模式的。首先是图。

2.5.1 上面的图的代码实现,首先是现金类CashSuper.h

#pragma once 

class CashSuper
{
public:
	virtual double AcceptCash(double money) = 0;
};

class CashNormal :public CashSuper
{
public:
	//正常收费,按原价返回
	double AcceptCash(double money)
	{
		return money;
	};
};

class CashRebate :public CashSuper
{
public:
	CashRebate(double rebate)
		:m_moneyRebate(1.0)
	{
		m_moneyRebate = rebate;
	}
	//打折后返回
	double AcceptCash(double money)
	{
		return money * m_moneyRebate;
	};
private:
	double m_moneyRebate;
};

class CashReturn :public CashSuper
{
public:
	CashReturn(double returnMoney,double condition)
		:m_moneyReturn(0.0)
		,m_moneyCondition(0.0)
	{
		m_moneyReturn = returnMoney;
		m_moneyCondition = condition;
	}

	double AcceptCash(double money)
	{
		double resultMoney = money;
		if (money > m_moneyCondition)
		{//减去返利值
			resultMoney = money - (money / m_moneyCondition )* m_moneyReturn;
		}
		return resultMoney;
	};
private:
	//返回现金
	double m_moneyReturn;
	//返利条件
	double m_moneyCondition;
};


2.5.2 Context类的实现

#pragma once
#include "CashSuper.h"

class Context
{
public:
	void SetContext(CashSuper* cashsuper)
	{
		m_pCashSuper = cashsuper;
	};

	double GetResult(double money)
	{
		return m_pCashSuper->AcceptCash(money);
	};

	~Context()
	{
		if (m_pCashSuper != NULL)
		{
			delete m_pCashSuper;
			m_pCashSuper = NULL;
		}
	};
private:
	CashSuper* m_pCashSuper;
};


2.5.3 客户端的调用方法

#include "stdafx.h"
#include <iostream>
#include "Context.h"

typedef enum _Type
{
	eNormal = 0,//正常收费
	e80Discount,
	e70Discount,
	e50Discount,
	eReturn		//满300减100
}MyDiscount;

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	double Price;
	double Num;
	int selectedIndex;
	//Price
	cout << "please Input you Price: " << endl;
	cin >> Price;
	//Num
	cout << "please Input you Num: " << endl;
	cin >> Num;
	//Discount
	cout << "please Input you Discount: " 
		<< "0:正常收费, 1:8折, 2:7折, 3:5折, 4:满300减100" << endl;
	cin >> selectedIndex;

	Context context;
	switch (selectedIndex)
	{
	case eNormal:
		context.SetContext( new CashNormal());
		break;
	case e80Discount:
		context.SetContext( new CashRebate(0.8));
		break;
	case e70Discount:
		context.SetContext( new CashRebate(0.7));
		break;
	case e50Discount:
		context.SetContext( new CashRebate(0.5));
		break;
	case eReturn:
		context.SetContext( new CashReturn(100, 300));
		break;
	default:
		context.SetContext( new CashNormal());
		break;
	}
	cout << "The total Price is "<< context.GetResult(Num * Price) << endl;
	return 0;
}

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

2.6 策略模式与简单工厂模式的结合,代码的耦合性进一步降低了。

2.6.1 首先是CashSuper.h,在这里基本没有什么改变

#pragma once 

class CashSuper
{
public:
	virtual double AcceptCash(double money) = 0;
};

class CashNormal :public CashSuper
{
public:
	//正常收费,按原价返回
	double AcceptCash(double money)
	{
		return money;
	};
};

class CashRebate :public CashSuper
{
public:
	CashRebate(double rebate)
		:m_moneyRebate(1.0)
	{
		m_moneyRebate = rebate;
	}
	//打折后返回
	double AcceptCash(double money)
	{
		return money * m_moneyRebate;
	};
private:
	double m_moneyRebate;
};

class CashReturn :public CashSuper
{
public:
	CashReturn(double returnMoney,double condition)
		:m_moneyReturn(0.0)
		,m_moneyCondition(0.0)
	{
		m_moneyReturn = returnMoney;
		m_moneyCondition = condition;
	}

	double AcceptCash(double money)
	{
		double resultMoney = money;
		if (money > m_moneyCondition)
		{//减去返利值
			resultMoney = money - (money / m_moneyCondition )* m_moneyReturn;
		}
		return resultMoney;
	};
private:
	//返回现金
	double m_moneyReturn;
	//返利条件
	double m_moneyCondition;
};


2.6.2 接下来是CashContext.h,简单工厂就在这里应用。

#pragma once
#include "CashSuper.h"

typedef enum _Type
{
	eNormal = 0,//正常收费
	e80Discount,
	e70Discount,
	e50Discount,
	eReturn		//满300减100
}MyDiscount;

class CashContext
{
public:
	CashContext(MyDiscount discount)
		:m_pCashSuper(NULL)
	{
		switch (discount)
		{
		case eNormal:
			m_pCashSuper = new CashNormal();
			break;
		case e80Discount:
			m_pCashSuper = new CashRebate(0.8);
			break;
		case e70Discount:
			m_pCashSuper = new CashRebate(0.7);
			break;
		case e50Discount:
			m_pCashSuper = new CashRebate(0.5);
			break;
		case eReturn:
			m_pCashSuper = new CashReturn(100, 300);
			break;
		default:
			m_pCashSuper = new CashNormal();
			break;
		}
	};

	double GetResult(double money)
	{
		return m_pCashSuper->AcceptCash(money);
	};
	
	~CashContext()
	{
		if (m_pCashSuper != NULL)
		{
			delete m_pCashSuper;
			m_pCashSuper = NULL;
		}
	};
private:
	CashSuper* m_pCashSuper;
};


2.6.3 客户端代码

#include "stdafx.h"
#include <iostream>
#include "CashContext.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	double Price;
	double Num;
	int selectedIndex;
	//Price
	cout << "please Input you Price: " << endl;
	cin >> Price;
	//Num
	cout << "please Input you Num: " << endl;
	cin >> Num;
	//Discount
	cout << "please Input you Discount: " 
		<< "0:正常收费, 1:8折, 2:7折, 3:5折, 4:满300减100" << endl;
	cin >> selectedIndex;

	CashContext cash((MyDiscount)selectedIndex);
	cout << "The total Price is "<< cash.GetResult(Price * Num) << endl;
	return 0;
}



 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的横打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值