简言:
最近在看设计模式,第一章为简单工厂模式,做一个小小的学习笔记,方便以后自己观看,本文代码是用c++完成,如有不足之处还请指出。
简单工厂模式:
模式:
简单工厂模式就是通过一个工厂类来实例化不同的对象,那我们为什么不直接实例化不同的对象,而非要通过一个工厂类呢?这样的好处是客户端只需要传入合适的参数就可以生产出想要的产品,并且程序更易于扩充,当以后新增一个产品时只需在工厂类中加入新产品的构造就好了,减少了程序模块间的耦合度。
角色:
简单工厂模式中有三个角色,工厂,抽象产品类,具体产品类。
工厂:顾名思义,就是用来生产具体产品。在代码中,就是用来实例化具体的对象。
抽象产品类:一般是具体产品类的基类,用来提供接口。
具体产品类:继承自抽象产品类,工厂创建的对象都是具体产品类的一个实例。
实例:
比如一个超市的收银,它虽然只是计算出商品的价格。但是当超市搞活动的时候,收银策略也可能会改变,可能会有全场打8折这种活动,或者满500减50等各种各样的活动。如果我们根据这些活动而不用简单工厂模式的方法去写代码的话,这个代码写出来就会很鸡肋,首先是有很多相似的地方会重复写,写一个打折的类和满减的类,他们当中都有一些最基本的属性,比如商品的名称,价格,这些都是一样的,不管是打折的类还是满减的类肯定都会算出商品的价格,只是实现不同而已,那完全可以抽象出一个类,然后去继承它。我们这里的实例的收银策略就是打折和满减这两种。
首先是工厂类(角色:工厂),它主要根据传入的参数不同去实现生产具体的产品,体现在代码上就是实例化不同的对象,我们这里是用基类指针指向子类对象来实现,这也是面向对象的多态性的一个体现。我们这里如果传入两个数值就是满减收银策略,如果只传入一个数值,就是打折收银策略。代码如下:
class CashierFactory
{
public:
CashierFactory() {};
~CashierFactory() {};
Cashier* creatCashier(int type1, int type2)
{
Cashier* newCashier = nullptr;
if (type2 == 0)
{
newCashier = new CashierDIscount(type1);
}
else
{
newCashier = new CashierReturn(type1, type2);
}
return newCashier;
};
};
其次是收银类(角色:抽象产品类),它定义了添加商品价格和改变商品价格两个方法,而这两个方法无论是哪种收银策略都是一样的,所以我们可以在收银类这里就实现它(即使万一假如有一种收银策略不一样也没事,我们定义的是虚函数,到时候覆盖就好了)。收银类还定义了四个纯虚函数提供获取商品价格和利润的四个接口,这四个纯虚函数必须在子类实现。下面话不多说,看代码:
Cashier.h
#pragma once
#include <map>
struct CommodityInfo
{
double m_costPrice; //进价
double m_retailPrice; //零售价
double m_wholeSalePrice; //批发价
int m_count; //售卖数量
};
class Cashier
{
public:
Cashier();
~Cashier();
virtual bool addCommdity(std::string commodity, CommodityInfo info);
virtual bool changeCommodityPrice(std::string commodity, CommodityInfo info);
virtual double returnAllCommodityTotalMoney() = 0;
virtual double returnOneCommodityTotalMoney(std::string commodity) = 0;
virtual double returnAllCommodityProfit() = 0;
virtual double returnOneCommodityProfit(std::string commodity) = 0;
protected:
static std::map<std::string, CommodityInfo> m_commodityPrice;
double m_oneCommodityTotalMoney;
double m_allCommodityTotalMoney;
};
Cashier.cpp
#include "Cashier.h"
CommodityInfo s = { 0,0,0,0 };
std::map<std::string, CommodityInfo> Cashier::m_commodityPrice = { {"",s} };
Cashier::Cashier()
{
m_oneCommodityTotalMoney = 0.0;
m_allCommodityTotalMoney = 0.0;
}
Cashier::~Cashier()
{
}
bool Cashier::addCommdity(std::string commodity, CommodityInfo info)
{
if (commodity.size() > 0 && info.m_retailPrice >= 0)
{
m_commodityPrice[commodity] = info;
return true;
}
else
{
return false;
}
}
bool Cashier::changeCommodityPrice(std::string commodity, CommodityInfo info)
{
if (commodity.size() > 0 && info.m_retailPrice >= 0)
{
if (m_commodityPrice.find(commodity) != m_commodityPrice.end())
{
m_commodityPrice[commodity] = info;
return true;
}
}
else
{
return false;
}
}
下面是打折策收类(角色:具体产品类),继承自收银类。当使用打折收银策略的时候,那获取商品的总价格就是需要在原有的价格上乘以折扣,所以在需要在打折类里定义一个变量为折扣,然后在计算价格时乘以折扣。下面是代码:
CashierDIscount.h
#pragma once
#include "Cashier.h"
class CashierDIscount :
public Cashier
{
public:
CashierDIscount(int discountRate);
~CashierDIscount();
virtual double returnOneCommodityTotalMoney(std::string commodity) override;
virtual double returnAllCommodityTotalMoney() override;
virtual double returnAllCommodityProfit() override;
virtual double returnOneCommodityProfit(std::string commodity) override;
private:
double m_discountRate;
};
CashierDIscount.cpp
#include "CashierDIscount.h"
CashierDIscount::CashierDIscount(int discountRate)
{
m_discountRate = discountRate;
}
CashierDIscount::~CashierDIscount()
{
}
double CashierDIscount::returnOneCommodityTotalMoney(std::string commodity)
{
if (m_commodityPrice.find(commodity) != m_commodityPrice.end())
{
m_oneCommodityTotalMoney = m_commodityPrice[commodity].m_count*m_commodityPrice[commodity].m_retailPrice*m_discountRate;
}
return m_oneCommodityTotalMoney;
}
double CashierDIscount::returnAllCommodityTotalMoney()
{
for (auto item : m_commodityPrice)
{
m_allCommodityTotalMoney += item.second.m_count*item.second.m_retailPrice*m_discountRate;
}
return m_allCommodityTotalMoney;
}
double CashierDIscount::returnAllCommodityProfit()
{
for (auto item : m_commodityPrice)
{
m_allCommodityTotalMoney += item.second.m_count*item.second.m_retailPrice*m_discountRate - item.second.m_count*item.second.m_costPrice*m_discountRate;
}
return m_allCommodityTotalMoney;
}
double CashierDIscount::returnOneCommodityProfit(std::string commodity)
{
if (m_commodityPrice.find(commodity) != m_commodityPrice.end())
{
m_oneCommodityTotalMoney = m_commodityPrice[commodity].m_count*(m_commodityPrice[commodity].m_retailPrice - m_commodityPrice[commodity].m_costPrice)*m_discountRate;
}
return m_oneCommodityTotalMoney;
}
接着是满减收银类(角色:具体产品类),继承自收银类。当使用满减收银策略的时候,需要先计算出商品的总价格,然后判断是否达到满减条件,如果达到满减条件就减少,反之则不变。具体实现的代码如下:
CashierReturn.h
#pragma once
#include "Cashier.h"
class CashierReturn :
public Cashier
{
public:
CashierReturn(int thresholdMoney, int returnMoney);
~CashierReturn();
virtual double returnOneCommodityTotalMoney(std::string commodity) override;
virtual double returnAllCommodityTotalMoney() override;
virtual double returnAllCommodityProfit() override;
virtual double returnOneCommodityProfit(std::string commodity) override;
private:
int m_thresholdMoney;
int m_returnMoney;
};
CashierReturn.cpp
#include "CashierReturn.h"
CashierReturn::CashierReturn(int thresholdMoney, int returnMoney)
{
m_thresholdMoney = thresholdMoney;
m_returnMoney = returnMoney;
}
CashierReturn::~CashierReturn()
{
}
double CashierReturn::returnOneCommodityTotalMoney(std::string commodity)
{
m_oneCommodityTotalMoney = m_commodityPrice[commodity].m_count*m_commodityPrice[commodity].m_retailPrice;
if (m_oneCommodityTotalMoney >= m_thresholdMoney)
{
m_oneCommodityTotalMoney = m_oneCommodityTotalMoney - m_returnMoney;
}
return m_oneCommodityTotalMoney;
}
double CashierReturn::returnAllCommodityTotalMoney()
{
for (auto item : m_commodityPrice)
{
m_allCommodityTotalMoney += item.second.m_count*item.second.m_retailPrice;
}
if (m_allCommodityTotalMoney >= m_thresholdMoney)
{
m_allCommodityTotalMoney = m_allCommodityTotalMoney - m_returnMoney;
}
return m_oneCommodityTotalMoney;
}
double CashierReturn::returnAllCommodityProfit()
{
double tmpCostMoney=0.0;
for (auto item : m_commodityPrice)
{
m_allCommodityTotalMoney += item.second.m_count*item.second.m_retailPrice;
tmpCostMoney += item.second.m_count*item.second.m_costPrice;
}
if (m_allCommodityTotalMoney >= m_thresholdMoney)
{
m_allCommodityTotalMoney = m_allCommodityTotalMoney - m_returnMoney - tmpCostMoney;
}
else
{
m_allCommodityTotalMoney = m_allCommodityTotalMoney - tmpCostMoney;
}
return m_allCommodityTotalMoney;
}
double CashierReturn::returnOneCommodityProfit(std::string commodity)
{
double tmpCostMoney=0.0;
m_oneCommodityTotalMoney = m_commodityPrice[commodity].m_count*m_commodityPrice[commodity].m_retailPrice;
tmpCostMoney = m_commodityPrice[commodity].m_count*m_commodityPrice[commodity].m_costPrice;
if (m_oneCommodityTotalMoney >= m_thresholdMoney)
{
m_oneCommodityTotalMoney = m_oneCommodityTotalMoney - m_returnMoney - tmpCostMoney;
}
else
{
m_oneCommodityTotalMoney = m_oneCommodityTotalMoney - tmpCostMoney;
}
return m_oneCommodityTotalMoney;
}
最后是主程序和运行效果:
int main()
{
CommodityInfo m_commodityInfo1 = { 2.5,5.0,4.5,12 };
CommodityInfo m_commodityInfo2 = { 45,98,78,6 };
CommodityInfo m_commodityInfo3 = { 6,12,9,15 };
CashierFactory m_cashierFactory;
Cashier* m_cashier = m_cashierFactory.creatCashier(300, 20);
m_cashier->addCommdity("烤鸭", m_commodityInfo2);
m_cashier->addCommdity("香蕉", m_commodityInfo3);
std::cout << "烤鸭的利润为:" << m_cashier->returnOneCommodityProfit("烤鸭") << std::endl;
std::cout << "香蕉的利润为:" << m_cashier->returnOneCommodityProfit("香蕉") << std::endl;
std::cout << "总共的利润为:" << m_cashier->returnAllCommodityProfit() << std::endl;
}
总结:
设计模式在C++里面更重要的是一种思想,什么思想呢?我觉得是充分运用面向对象的封装,抽象,多态,继承这几大特性去提高代码的复用性,灵活性,去降低整个程序中各个模块组件之间的耦合度。但是,我觉得这种思想在没有完全掌握,完全的理解之前,如果生搬硬套的使用设计模式,反而会事与愿违,增加工作量。暂时就想到这些,以后有新的理解,再回来补上。