先阅读完《大话设计模式》&《设计模式--可复用面向对象软件的基础》中有关State模式的章节,对状态模式有个较为深入的了解,然后继续《重构》中1.4节利用State模式表现不同影片的价格状态。
步骤1:
运用Replace Type Code with State/Strategy,将与类型相关的行为搬移至State模式内
步骤2:
运用Move Method将switch语句搬移到Price类
步骤3:
运用Replace Conditional with Polymorphism 去掉switch语句
最后结果代码:
movie.h:
#ifndef MOVIE_H
#define MOVIE_H
#include <string>
#include "price.h"
using std::string;
class Movie
{
public:
Movie(string title = "empty", int priceCode = 0);
double getCharge(int daysRented);
int getFrequentRenterPoints(int daysRented);
int getPriceCode();
void setPriceCode(int arg);
string getTitle();
public:
static const int REGULAR;
static const int NEW_RELEASE;
static const int CHILDRENS;
private:
string _title;
Price* _price;
};
#endif //MOVIE_H
movie.cpp:
#include "movie.h"
#include <iostream>
using namespace std;
const int Movie::REGULAR = 0;
const int Movie::NEW_RELEASE = 1;
const int Movie::CHILDRENS = 2;
Movie::Movie(string title , int priceCode)
{
_title = title;
setPriceCode(priceCode);
}
double Movie::getCharge(int daysRented)
{
return _price->getCharge(daysRented);
}
int Movie::getFrequentRenterPoints(int daysRented)
{
return _price->getFrequentRenterPoints(daysRented);
}
int Movie::getPriceCode()
{
return _price->getPriceCode();
}
void Movie::setPriceCode(int arg)
{
switch(arg)
{
case REGULAR:
_price = new RegularPrice();
break;
case CHILDRENS:
_price = new ChildrensPrice();
case NEW_RELEASE:
_price = new NewReleasePrice();
break;
default:
cerr << "Incorrect Price Code" << endl;
}
}
string Movie::getTitle()
{
return _title;
}
price.h:
#ifndef PRICE_H
#define PRICE_H
class Price
{
public:
virtual int getPriceCode() = 0;
virtual double getCharge(int daysRented) = 0;
virtual int getFrequentRenterPoints(int daysRented);
};
class ChildrensPrice : public Price
{
public:
virtual int getPriceCode();
virtual double getCharge(int daysRented);
};
class NewReleasePrice : public Price
{
public:
virtual int getPriceCode();
virtual double getCharge(int daysRented);
virtual int getFrequentRenterPoints(int daysRented);
};
class RegularPrice : public Price
{
public:
virtual int getPriceCode();
virtual double getCharge(int daysRented);
};
#endif //PRICE_H
price.cpp:
#include "price.h"
#include "movie.h"
int Price::getFrequentRenterPoints(int daysRented)
{
if ( (getPriceCode() == Movie::NEW_RELEASE) && daysRented > 1 )
return 2;
else
return 1;
}
int ChildrensPrice::getPriceCode()
{
return Movie::CHILDRENS;
}
double ChildrensPrice::getCharge(int daysRented)
{
double result = 1.5;
if (daysRented > 3)
result += (daysRented - 3) * 1.5;
return result;
}
int NewReleasePrice::getPriceCode()
{
return Movie::NEW_RELEASE;
}
double NewReleasePrice::getCharge(int daysRented)
{
return daysRented * 3;
}
int NewReleasePrice::getFrequentRenterPoints(int daysRented)
{
return (daysRented > 1) ? 2 : 1;
}
int RegularPrice::getPriceCode()
{
return Movie::REGULAR;
}
double RegularPrice::getCharge(int daysRented)
{
double result = 2;
if (daysRented > 2)
result += (daysRented - 2) * 1.5;
return result;
}