概述
影片出租店是《重构:改善既有代码的设计》里面的第一个例子。使用了多种重构方法。
影片出租店:计算每一位顾客的消费金额并打印详单。
操作者告诉程序:顾客租了哪些影片,租期多长,程序便根据租赁时间和影片类型算出费用。影片分为三类:普通片,儿童片和新片。除了计算费用,还要为常客计算积分,积分会根据租片种类是否为新片而有不同。
第6次重构:
- 运用多态取代与价格相关的条件逻辑
- 有多种影片类型,他们的计费方式和积分方式不同。我们可以用继承机制来表现不同的影片类型
- 用多态来取代switch语句。但是此处不可以。因为一个对象在创建后,其作为子类的特性就不能再修改了。
- 使用状态模式/策略模式来解决这个问题
- 先运用 Replace Type Code with State/Stategy,将类型相关的行为搬移至state/Stategy模式中。
- 使用Self Encapsulate Field,确保任何时候都通过取值函数(getter)和设置函数(setter)来访问类型代码。
- 然后运用MoveMethod将switch语句移到Price类。
- 最后运用Replace Conditional with Polymorphism去掉switch 语句
修改后的代码:
Refector_1.h
#ifndef REFECTOR_1_H
#define REFECTOR_1_H
#include <QString>
#include <QVector>
class Price
{
public:
virtual int GetPriceCode() = 0;
virtual double GetCharge(int daysRented) = 0;
};
class ChildrenPrice : public Price
{
public:
int GetPriceCode();
double GetCharge(int daysRented);
};
class NewReleasePrice : public Price
{
public:
int GetPriceCode();
double GetCharge(int daysRented);
};
class RegularPrice : public Price
{
public:
int GetPriceCode();
double GetCharge(int daysRented);
};
class ExceptionPrice : public Price
{
public:
ExceptionPrice();
int GetPriceCode();
double GetCharge(int daysRented);
};
class Movie
{
public:
Movie(QString title, int priceCode);
const static int CHILDREN = 2;
const static int REGULAR = 0;
const static int NEW_RELEASE = 1;
int GetPriceCode();
void SetPriceCode(int priceCode);
QString GetTitle();
double GetCharge(int daysRented);
int GetFrequentRenterPoints(int daysRented);
private:
QString m_Title;
int m_PriceCode;
Price *m_pPrice;
};
class Rental
{
public:
Rental(Movie *movie, int daysRented);
int GetDaysRented();
double GetCharge();
Movie* GetMovie();
int GetFrequentRenterPoints();
private:
Movie* m_Movie;
int m_DaysRented;
};
class Customer
{
public:
Customer(QString name);
void AddRental(Rental *rental);
QString GetName();
QVector<Rental *> GetRentals();
QString Statement();
double AmountFor(Rental *rental);
double GetTotalCharge();
int GetTotalFrequentRenterPoints();
private:
QString m_Name;
QVector<Rental *> m_Rentals;
};
#endif // REFECTOR_1_H
Refector_1.cpp
#include "Refector_1.h"
#include <QDebug>
Movie::Movie(QString title, int priceCode)
{
m_Title = title;
SetPriceCode(priceCode);
}
int Movie::GetPriceCode()
{
return m_pPrice->GetPriceCode();
}
void Movie::SetPriceCode(int priceCode)
{
switch (priceCode) {
case REGULAR:
m_pPrice = new RegularPrice();
break;
case CHILDREN:
m_pPrice = new ChildrenPrice();
break;
case NEW_RELEASE:
m_pPrice = new NewReleasePrice();
break;
default:
m_pPrice = new ExceptionPrice();
}
}
QString Movie::GetTitle()
{
return m_Title;
}
double Movie::GetCharge(int daysRented)
{
return m_pPrice->GetCharge(daysRented);
}
int Movie::GetFrequentRenterPoints(int daysRented)
{
if (NEW_RELEASE == (GetPriceCode()) &&
daysRented > 1 )
{
return 2;
}
return 1;
}
Rental::Rental(Movie *movie, int daysRented)
{
m_Movie =movie;
m_DaysRented = daysRented;
}
int Rental::GetDaysRented()
{
return m_DaysRented;
}
double Rental::GetCharge()
{
return GetMovie()->GetCharge(GetDaysRented());
}
Movie *Rental::GetMovie()
{
return m_Movie;
}
int Rental::GetFrequentRenterPoints()
{
return GetMovie()->GetFrequentRenterPoints(GetDaysRented());
}
Customer::Customer(QString name)
{
m_Name = name;
}
void Customer::AddRental(Rental *rental)
{
m_Rentals.push_back(rental);
}
QString Customer::GetName()
{
return m_Name;
}
QVector<Rental *> Customer::GetRentals()
{
return m_Rentals;
}
QString Customer::Statement()
{
QString result = "Rental Record for " + GetName() + "n";
for (Rental *rental : GetRentals())
{
result += "t" + rental->GetMovie()->GetTitle() + "t" + QString("%1").arg(AmountFor(rental)) + "n";
}
result += "Amount owed is " + QString("%1").arg(GetTotalCharge()) + "n";
result += "You earned " + QString("%1").arg(GetTotalFrequentRenterPoints()) + " frequent renter points";
qDebug() << qPrintable(result) ;
return result;
}
double Customer::AmountFor(Rental *rental)
{
return rental->GetCharge();
}
double Customer::GetTotalCharge()
{
double result = 0;
for (Rental *rental : GetRentals())
{
result += AmountFor(rental);
}
return result;
}
int Customer::GetTotalFrequentRenterPoints()
{
int result = 0;
for (Rental *rental : GetRentals())
{
result += rental->GetFrequentRenterPoints();
}
return result;
}
int ChildrenPrice::GetPriceCode()
{
return Movie::CHILDREN;
}
double ChildrenPrice::GetCharge(int daysRented)
{
double Result = 0;
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 RegularPrice::GetPriceCode()
{
return Movie::REGULAR;
}
double RegularPrice::GetCharge(int daysRented)
{
double Result = 0;
Result += 2;
if (daysRented > 2)
{
Result += (daysRented - 2)*1.5;
}
return Result;
}
ExceptionPrice::ExceptionPrice()
{
//trigger except handler
qDebug() << "Except occur";
}
int ExceptionPrice::GetPriceCode()
{
return -1;
}
double ExceptionPrice::GetCharge(int daysRented)
{
return 0;
}
最后
以上就是阔达白昼为你收集整理的影片出租店 重构方法(7)的全部内容,希望文章能够帮你解决影片出租店 重构方法(7)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复