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; } };