日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《重构-改善既有代码的设计》-第1例:租赁影片(1)

發布時間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《重构-改善既有代码的设计》-第1例:租赁影片(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

買了《重構 - 改善既有代碼的設計?》一書,一直沒有好好看,大致過了下也覺得只是有點點印象而已,最后還是決定把代碼敲一次,記錄一下這些學習過程。

?

第一例:租賃影片

程序說明:顧客租了哪些影片,租期多長,根據租賃時間和影片類型算出費用和積分。

1. 分解并重組statement()?

原代碼如下有3個類。?

?

package bean; /*** 租賃訂單* @author Administrator*/ public class Rental {private Movie _movie ; // 影片private int _daysRented; // 租賃天數public Rental(Movie _movie, int _daysRented) {this._movie = _movie;this._daysRented = _daysRented;}public Movie getMovie() {return _movie;}public int getDaysRented() {return _daysRented;}}

?

package bean;/*** 影片* @author Administrator*/ public class Movie {public static final int CHILDRENS = 2; // 兒童片public static final int REGULAR = 0; // 普通片public static final int NEW_RELEASE = 1; // 新片private String _title;private int _priceCode;public Movie(String _title, int _priceCode) {this._title = _title;this._priceCode = _priceCode;}public int getPriceCode() {return _priceCode;}public void setPriceCode(int _priceCode) {this._priceCode = _priceCode;}public String getTitle() {return _title;}}

?

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();// 確定每種片子的租金switch(each.getMovie().getPriceCode()){case Movie.REGULAR:thisAmount += 2;if(each.getDaysRented() > 2 ){thisAmount += (each.getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:thisAmount += each.getDaysRented()*3;break;case Movie.CHILDRENS:thisAmount += 1.5;if(each.getDaysRented() > 3 ){thisAmount += (each.getDaysRented() - 3) * 1.5;}break;}// 增加積分frequentRenterPoints ++;// 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thislAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}}


1.1 抽離switch 語句到獨立方法

1.1.1 Customer類改為:

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();thisAmount = amountFor(each); // 計算租金// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thisAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}// 計算租金private int amountFor(Rental each){int thisAmount = 0; // 租金// 確定每種片子的租金switch(each.getMovie().getPriceCode()){case Movie.REGULAR:thisAmount += 2;if(each.getDaysRented() > 2 ){thisAmount += (each.getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:thisAmount += each.getDaysRented()*3;break;case Movie.CHILDRENS:thisAmount += 1.5;if(each.getDaysRented() > 3 ){thisAmount += (each.getDaysRented() - 3) * 1.5;}break;}return thisAmount;}}

?

?

1.1.2 注意?amountFor 方法的返回類型應該是double類型:

?Customer類改為:

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();thisAmount = amountFor(each); // 計算租金// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thisAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}// 計算租金private double amountFor(Rental each){double thisAmount = 0; // 租金// 確定每種片子的租金switch(each.getMovie().getPriceCode()){case Movie.REGULAR:thisAmount += 2;if(each.getDaysRented() > 2 ){thisAmount += (each.getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:thisAmount += each.getDaysRented()*3;break;case Movie.CHILDRENS:thisAmount += 1.5;if(each.getDaysRented() > 3 ){thisAmount += (each.getDaysRented() - 3) * 1.5;}break;}return thisAmount;}}


1.3 ?變量名稱應該見名知意:好的代碼應該清楚的表達出自己的功能,變量名稱是代碼清晰的一個關鍵。

?

amountFor方法中局部變量 thisAmount , 參數each 要改名。

改變量名 ,?Customer類改為:

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();thisAmount = amountFor(each); // 計算租金// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thisAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}// 計算租金private double amountFor(Rental aRental){double result = 0; // 租金// 確定每種片子的租金switch(aRental.getMovie().getPriceCode()){case Movie.REGULAR:result += 2;if(aRental.getDaysRented() > 2 ){result += (aRental.getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += aRental.getDaysRented()*3;break;case Movie.CHILDRENS:result += 1.5;if(aRental.getDaysRented() > 3 ){result += (aRental.getDaysRented() - 3) * 1.5;}break;}return result;}}

?

?

1.4 函數應該放在它所使用的數據所屬的對象中, 顧客租金的計算應該移動到Rental類中去。

?

?

?

Rental 類改為 : ?(計算租金方法去掉參數并改名 )

?

package bean; /*** 租賃訂單* @author Administrator*/ public class Rental {private Movie _movie ; // 影片private int _daysRented; // 租賃天數public Rental(Movie _movie, int _daysRented) {this._movie = _movie;this._daysRented = _daysRented;}public Movie getMovie() {return _movie;}public int getDaysRented() {return _daysRented;}// 計算租金double getCharge(){double result = 0; // 租金// 確定每種片子的租金switch(getMovie().getPriceCode()){case Movie.REGULAR:result += 2;if(getDaysRented() > 2 ){result += (getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += getDaysRented()*3;break;case Movie.CHILDRENS:result += 1.5;if(getDaysRented() > 3 ){result += (getDaysRented() - 3) * 1.5;}break;}return result;}}


原顧客類中amountFor方法直接調用計算租金方法即可,Customer 類改為:

?

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();thisAmount = amountFor(each); // 計算租金// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thisAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}// 計算租金private double amountFor(Rental aRental){return aRental.getCharge();}}


1.5 ?去掉舊函數amountFor,直接調用新函數getCharge。Customer類改為 :?

?

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){double thisAmount = 0; // 租金Rental each = (Rental)rentals.nextElement();thisAmount = each.getCharge(); // 計算租金// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(thisAmount)+"\n";totalAmount += thisAmount;}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}}


1.6 ?盡量去掉臨時變量,臨時變量會導致大量參數的傳遞,沒有必要。 thisAmount 是個多余的臨時變量,直接去掉。

?

Customer?改為:

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();// 增加積分frequentRenterPoints ++; // 新片+租賃時間達2天 積分+1 if(each.getMovie().getPriceCode() == Movie.NEW_RELEASE && each.getDaysRented() > 1){frequentRenterPoints ++;}// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(each.getCharge())+"\n";totalAmount += each.getCharge();}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}}

?

1.7 把積分計算方法放到Rental類中,寫為常客積分計算方法(getFrequentRenterPoints),并改變Customer類中積分計算代碼 。

?

Rental類改為:

?

package bean; /*** 租賃訂單* @author Administrator*/ public class Rental {private Movie _movie ; // 影片private int _daysRented; // 租賃天數public Rental(Movie _movie, int _daysRented) {this._movie = _movie;this._daysRented = _daysRented;}public Movie getMovie() {return _movie;}public int getDaysRented() {return _daysRented;}// 計算租金double getCharge(){double result = 0; // 租金// 確定每種片子的租金switch(getMovie().getPriceCode()){case Movie.REGULAR:result += 2;if(getDaysRented() > 2 ){result += (getDaysRented() - 2) * 1.5;}break;case Movie.NEW_RELEASE:result += getDaysRented()*3;break;case Movie.CHILDRENS:result += 1.5;if(getDaysRented() > 3 ){result += (getDaysRented() - 3) * 1.5;}break;}return result;}// 常客積分計算int getFrequentRenterPoints(){// 增加積分int frequentRenterPoints =0;frequentRenterPoints++; // (新片+租賃時間達2天 積分+1 )if(getMovie().getPriceCode() == Movie.NEW_RELEASE && getDaysRented() > 1){frequentRenterPoints ++;}return frequentRenterPoints;}}


Customer類中statement方法改為:

?

?

/*** 生成訂單* @return*/public String statement(){double totalAmount = 0; // 總租金 int frequentRenterPoints = 0; // 積分Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();// 積分frequentRenterPoints += each.getFrequentRenterPoints();// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(each.getCharge())+"\n";totalAmount += each.getCharge();}// 頁腳result +="Amount owed is "+ String.valueOf(totalAmount)+"\n";result +="You eared "+String.valueOf(frequentRenterPoints)+"frequent renter points";return result;}

?

1.8 去掉statement方法中的2個臨時變量:totalAmount 和?frequentRenterPoints 。抽離出對應計算方法,并調用。

?

Customer?類改為:

?

package bean;import java.util.Enumeration; import java.util.Vector;/*** 顧客* @author Administrator*/ public class Customer {private String _name; // 顧客名字private Vector _rentals = new Vector(); // 租賃訂單數組public Customer(String name) {super();this._name = name;}public void addRental(Rental arg){_rentals.addElement(arg);}public String getName() {return _name;}/*** 生成訂單* @return*/public String statement(){Enumeration rentals = _rentals.elements();String result = "Rental Record for "+ getName() + "\n";while( rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();// 本次租賃記錄說明result += "\t"+each.getMovie().getTitle()+"\t"+ String.valueOf(each.getCharge())+"\n";}// 頁腳result +="Amount owed is "+ String.valueOf(getTotalCharge())+"\n";result +="You eared "+String.valueOf(getTotalFrequentRenterPoints())+"frequent renter points";return result;}// 計算總積分private int getTotalFrequentRenterPoints(){int result = 0;Enumeration rentals = _rentals.elements();while(rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();result += each.getFrequentRenterPoints();}return result;}// 計算總租金private double getTotalCharge(){double result = 0;Enumeration rentals = _rentals.elements();while(rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();result += each.getCharge();}return result;}}

?

本步改寫作用說明:

?

?這里雖然從1個循環變為3個,但是多了2個查詢函數。

1) ?使得Customer 類中的任何代碼都可以調用這些查詢函數。

2) ?若系統其它部分需要這些信息,也可以輕松地將查詢函數加入?Customer 類接口。而若沒有這些查詢波函數,其它函數就必須了解 ?Rental 類,并自行建立循環。

?

?

1.9 加功能:打印憑條。

statement 方法改為 htmlStatement :

?

?

/*** 生成訂單(打印憑條)* @return*/public String htmlStatement(){Enumeration rentals = _rentals.elements();String result = "<P><H1>Rentals for <EM> "+ getName() + "</EM></H1></P>\n";while( rentals.hasMoreElements()){Rental each = (Rental)rentals.nextElement();// 本次租賃記錄說明result += each.getMovie().getTitle()+":"+ String.valueOf(each.getCharge())+"<BR>\n";}// 頁腳result +="<P>You owe <EM>"+ String.valueOf(getTotalCharge())+"</EM></P>\n";result +="<P> on this rental you earned <EM> "+String.valueOf(getTotalFrequentRenterPoints())+"</EM> frequent renter points </P>";return result;}

?

?

?

?

?

未完,見 ?:?重構-改善既有代碼的設計-第1例:租賃影片(2)

?

?

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的《重构-改善既有代码的设计》-第1例:租赁影片(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。