我是靠谱客的博主 阔达白昼,最近开发中收集的这篇文章主要介绍影片出租店 重构方法(7),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

 影片出租店是《重构:改善既有代码的设计》里面的第一个例子。使用了多种重构方法。
影片出租店:计算每一位顾客的消费金额并打印详单。
操作者告诉程序:顾客租了哪些影片,租期多长,程序便根据租赁时间和影片类型算出费用。影片分为三类:普通片,儿童片和新片。除了计算费用,还要为常客计算积分,积分会根据租片种类是否为新片而有不同。


第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)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部