2. 分解并重组statement

(1)提炼switch语句到独立函数(amountFor)和注意事项。

  ①先找出函数内的局部变量和参数:each和thisAmount,前者在switch语句内未被修改,后者会被修改。

  ②任何不会被修改的变量都可以当成参数传入新的函数,如将each为作为参数传给amountFor()的形参

  ③至于会被修改的变量要格外小心,如果只有一个变量会被修改(如thisAmount),则可以当作新函数的返回值

【实例分析】影片出租2

//顾客类(用来表示顾客)
class Customer
{
private:
    string name; //顾客姓名
    vector<Rental*> rentals; //每个租赁记录
public:
    Customer(string name)
    {
        this->name = name;
    }

    void addRental(Rental* value)
    {
        rentals.push_back(value);
    }

    string getName(){return name;}

    //statement(报表),生成租赁的详单
    string statement()
    {
        string ret = "Rental Record for " + name + "\n";
        double totalAmount = 0;  //总租金额
        int frequentReterPoints = 0; //常客积分

        vector<Rental*>::iterator iter = rentals.begin();
        while( iter != rentals.end())
        {
            double thisAmount = 0;   //每片需要的租金
            Rental& each = *(*iter);

            //each在switch不会变化,做为参数转给amountFor,而thisAmount作为返回值
            thisAmount = amountFor(each);

            //常客积分
            ++frequentReterPoints;

            //如果是新片且租期超过1天以上,则额外送1分积分
            if ((each.getMovie().getPriceCode() == Movie::NEW_RELEASE) &&
                each.getDaysRented() > 1)  ++frequentReterPoints;

            //显示每个租赁记录
            ostringstream oss;
            oss << thisAmount;
            ret += "\t" + each.getMovie().getTitle() + "\t" +
                 oss.str()+ "\n";

            totalAmount +=thisAmount;

            ++iter;
        }

        //增加页脚注释
        ostringstream oss;
        oss << totalAmount;
        ret += "Amount owed is " + oss.str() + "\n";

        oss.str("");
        oss << frequentReterPoints;
        ret += "You earned " + oss.str() +"\n";
        return ret;
    }

    //计算金额switch代码从statement中分离出来
    //但这个函数存在一个问题:该函数是Customer类的成员函数,但没有用于Customer
    //类中的任何信息,却使用了Rental类。因此可以将这段代码转移到Rental类中
    double amountFor(Rental& aRental) //参数相当于原statement中的each
    {
        double result = 0 ;//相当于statement中的thisamount;

        switch(aRental.getMovie().getPriceCode())
        {
        case Movie::REGULAR:
            result += 2;    //普通片基本租金为2元
            if(aRental.getDaysRented() > 2)  //超过2天的每天加1.5元
                result +=(aRental.getDaysRented() - 2 ) * 1.5;
            break;
        case Movie::NEW_RELEASE:
            result += aRental.getDaysRented() * 3;    //新片的租金
            break;
        case Movie::CHILDRENS:
            result += 1.5;    //儿童片基本租金为1.5元
            if(aRental.getDaysRented() > 3)  //超过3天的每天加1.5元
                result +=(aRental.getDaysRented() - 3 ) * 1.5;
            break;
        }

       return result;
    }
};
View Code

相关文章: