电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java如何利用狀態(tài)模式(state pattern)替代if else

瀏覽:22日期:2022-08-20 18:23:51

大多數(shù)開發(fā)人員現(xiàn)在還在使用if else的過程結(jié)構(gòu),曾看過jdon的banq大哥寫的一篇文章,利用command,aop模式替代if else過程結(jié)構(gòu)。當(dāng)時(shí)還不太明白,這幾天看了《重構(gòu)》第一章的影片租賃案例,感觸頗深。下面我來談一談為什么要用state pattern替代if else,替代if else有什么好處,以及給出詳細(xì)代碼怎么替代if else。本文參考jdon的“你還在使用if else嗎?”及《重構(gòu)》第一章。

首先我們模仿影片租賃過程,顧客租憑影片,影片分為兒童片、普通片、新片。根據(jù)影片類型及租憑天數(shù)價(jià)格各不相同(優(yōu)惠程度不同),用戶累計(jì)積分不同。

OK ,現(xiàn)在我們使用 if else 表示。

package com.qujingbo.movie; /** * <p/> Title:影片基類 * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:47:55 * </p> * * @author EOMS 曲靜波 * @version 1.0 */ public class Movie { // 普通片標(biāo)識(shí) public static int REGULAR = 1 ; // 新片標(biāo)識(shí) public static int NEW_RELEASE = 2 ; // 兒童片標(biāo)識(shí) public static int CHILDREN = 3 ; /** * 獲取租賃影片總價(jià) * * @param movieCode * 影片類型 * @param days * 租憑天數(shù) * @return 租賃影片總價(jià) * @throws MovieException * 沒有影片類型拋出異常 */ public double getCharge( int movieCode, int days) throws MovieException { double result = 0 ; // 普通片 if (movieCode == Movie.REGULAR) // 單價(jià)為2 { result = 2 ; // 如果租賃天數(shù)大于2則,則優(yōu)惠 if (days > 2 ) { result += (days - 2 ) * 1.5 ; } // 返回總價(jià) return result; } // 最新發(fā)布片 else if (movieCode == Movie.NEW_RELEASE) { // 新片沒有優(yōu)惠,單價(jià)為3 return days * 3 ; } // 兒童片 else if (movieCode == Movie.CHILDREN) { // 影片單價(jià) result = 1.5 ; // 如果租賃時(shí)間大于3天則做價(jià)格優(yōu)惠 if (days > 3 ) { result += (days - 3 ) * 1.5 ; } // 返回租賃影片總價(jià) return result; } else throw new MovieException( ' 影片不存在 ' ); } /** * 獲取租賃影片積分 * * @param movieCode * 影片類型 * @param days * 租憑天數(shù) * @return 租賃影片積分 * @throws MovieException * 沒有影片類型拋出異常 */ public double getIntegral( int movieCode, int days) throws MovieException { // 普通片 if (movieCode == Movie.REGULAR) return days * 2 ; // 最新發(fā)布片 else if (movieCode == Movie.NEW_RELEASE) return days * 3 ; // 兒童片 else if (movieCode == Movie.CHILDREN) return days * 1.5 ; else throw new MovieException( ' 影片不存在 ' ); }}

OK ,我們看一下,現(xiàn)在的 Movie 完全符合租賃需求,通過 getIntegral(int movieCode,int days) 和 getCharge(int movieCode,int days) 來獲得租賃積分及租賃價(jià)格。從開閉原則角度來看,如果要添加新的影片類型,我們必須修改 getIntegral(int movieCode,int days) 和 getCharge(int movieCode,int days) 這兩個(gè)方法。而若要改變租賃價(jià)格、積分的優(yōu)惠規(guī)則時(shí),仍需要修改 getIntegral(int movieCode,int days) 和 getCharge(int movieCode,int days) 方法?,F(xiàn)在看來,只有三種影片類型,維護(hù)還較方便。而當(dāng)影片類型較多時(shí),例如 10 種, 100 種影片類型,這樣就是不可以想像的維護(hù)。

現(xiàn)在我們來看一下,使用 state pattern 來代替 if else 。先來個(gè)類圖。

Java如何利用狀態(tài)模式(state pattern)替代if else

首先我們建立一個(gè) abstract class Price 做為影片類型的基類,基類中含有兩個(gè) abstract 方法,獲取總價(jià)格 getCharge(int days), 獲取總積分 getIntegral(int days) 方法 , 繼承 abstract classPrice 的三個(gè)影片類型兒童片 class ChilerenPrice, 普通片 class RegularPrice, 最新片 class NewReleasePrice 。分別實(shí)現(xiàn) getCharge(int days),getIntegral(int days) 方法,實(shí)現(xiàn)方法寫入計(jì)算價(jià)格的優(yōu)惠方案及積分的方案。當(dāng)需要修改方案時(shí),我們只需在某個(gè)影片類的方法中對(duì)應(yīng)修改就可以。若新增一個(gè)影片分類時(shí),我們只需新增一個(gè)實(shí)現(xiàn)類實(shí)現(xiàn) abstract class Price 類就 OK 。

class Movie 代表影片,其關(guān)聯(lián)一個(gè) Price 類,而 setPrice(String movieClass) 方法類似于一個(gè)工廠類,傳入 movieClass 為包名類名,用 java 反射機(jī)制實(shí)例化一個(gè)具體傳入 movieClass 的影片類型實(shí)現(xiàn)類,這樣我們通過這幾行代碼就可以獲得該影片類型的價(jià)格和積分。

Movie regularMovie = new Movie();regularMovie.setPrice(Movie.REGULAR);System.out.println( ' 普通影片租賃10天的價(jià)格 ' + regularMovie.getPrice().getCharge( 10 ));System.out.println( ' 普通影片租賃10天的積分 ' + regularMovie.getPrice().getIntegral( 10 ));

下面我們給出詳細(xì)代碼

abstract class Price價(jià)格基類

package com.qujingbo.movie;/** * <p/> Title: * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:48:22 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public abstract class Price { /** * 獲取租賃影片價(jià)格需實(shí)現(xiàn)該此方法 * * @param days * 租賃天數(shù) * @return 返回影片價(jià)格 */ public abstract double getCharge(int days); /** * 獲取租賃影片積分需實(shí)現(xiàn)此方法 * * @param days * 租賃天數(shù) * @return 返回影片積分 */ public abstract double getIntegral(int days);}

兒童片ChildrenPrice類,實(shí)現(xiàn)abstract class Price ,實(shí)現(xiàn)兒童片租賃總價(jià)getCharge(int days)及兒童片租賃積分getIntegral(int days)。

package com.qujingbo.movie;/** * <p/> Title:兒童片租賃積分、價(jià)格實(shí)現(xiàn) * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:49:04 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class ChildrenPrice extends Price { /** * 兒童片返回租賃積分,兒童片積分規(guī)則為: 根據(jù) */ public double getIntegral(int days) { // 返回租賃影片積分 return days * 1.5; } /** * 兒童片返回租賃價(jià)格 */ public double getCharge(int days) { // 影片單價(jià) double result = 1.5; // 如果租賃時(shí)間大于3天則做價(jià)格優(yōu)惠 if (days > 3) { result += (days - 3) * 1.5; } // 返回租賃影片總價(jià) return result; }}

普通片RegularlPrice類,實(shí)現(xiàn)abstract class Price ,實(shí)現(xiàn)普通片租賃總價(jià)getCharge(int days)及普通片租賃積分getIntegral(int days)。

package com.qujingbo.movie;/** * <p/> Title:普通片租賃積分、價(jià)格實(shí)現(xiàn) * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:50:10 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class RegularlPrice extends Price { /** * 普通片返回租賃積分,普通片積分規(guī)則 */ public double getIntegral(int days) { // 返回租賃影片積分 return days * 2; } /** * 普通片返回租賃價(jià)格 */ public double getCharge(int days) { // 單價(jià)為2 double result = 2; // 如果租賃天數(shù)大于2則,則優(yōu)惠 if (days > 2) { result += (days - 2) * 1.5; } // 返回總價(jià) return result; }}

最新發(fā)布片NewReleasePrice類,實(shí)現(xiàn)abstract class Price ,實(shí)現(xiàn)最新發(fā)布片租賃總價(jià)getCharge(int days)及最新發(fā)布片租賃積分getIntegral(int days)。

package com.qujingbo.movie;/** * <p/> Title:最新發(fā)布片租賃積分、價(jià)格實(shí)現(xiàn) * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:48:51 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class NewReleasePrice extends Price { /** * 最新發(fā)布片返回租賃積分,最新發(fā)布片積分規(guī)則 */ public double getIntegral(int days) { // 返回租賃影片積分 return days * 3; } /** * 最新發(fā)布片返回租賃價(jià)格 */ public double getCharge(int days) { // 新片沒有優(yōu)惠,單價(jià)為3 return days * 3; }}

電影Movie類,setPrice(String movieClass)(工廠)方法,通過java反射機(jī)制實(shí)現(xiàn)movieClass(包名,類名)類。若沒有movieClass這個(gè)類,則拋出MovieException異常。

package com.qujingbo.movie;/** * <p/> Title:影片類 * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 15:47:55 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class Movie { // 普通片標(biāo)識(shí) public static String REGULAR = 'com.qujingbo.movie.RegularlPrice'; // 新片標(biāo)識(shí) public static String NEW_RELEASE = 'com.qujingbo.movie.NewReleasePrice'; // 兒童片標(biāo)識(shí) public static String CHILDREN = 'com.qujingbo.movie.ChildrenPrice'; private Price price; public Price getPrice() { return price; } /** * 確定返回具體某個(gè)影片類型的實(shí)現(xiàn)類,有點(diǎn)像工廠 * * @param movieCode * 影片類型 * @throws MovieException * 若無影片類型則拋異常。 */ public void setPrice(String movieClass) throws MovieException { try { Class cls = Class.forName(movieClass); this.price = (Price) cls.newInstance(); } catch (Exception e) { throw new MovieException('影片不存在'); } }}

給出MovieException源碼。

package com.qujingbo.movie;/** * <p/> Title:自定義異常 * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 19:21:08 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class MovieException extends Exception { public MovieException(String msg) { super(msg); }}

下面模訪一個(gè)顧客租賃影片。

package com.qujingbo.movie;/** * <p/> Title: * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 19:26:23 * </p> * * @author EOMS 曲靜波 * @version 1.0 */public class Customer { /** * 消費(fèi)(測(cè)試程序) * * @throws MovieException * 若沒有影片,拋出異常 */ public void consume() throws MovieException { // 普通電影 Movie regularMovie = new Movie(); regularMovie.setPrice(Movie.REGULAR); // 最新發(fā)布電影 Movie newReleaseMovie = new Movie(); newReleaseMovie.setPrice(Movie.NEW_RELEASE); // 兒童電影 Movie childrenMovie = new Movie(); childrenMovie.setPrice(Movie.CHILDREN); System.out.println('普通影片租賃10天的價(jià)格' + regularMovie.getPrice().getCharge(10)); System.out.println('最新影片租賃10天的價(jià)格' + newReleaseMovie.getPrice().getCharge(10)); System.out.println('兒童影片租賃10天的價(jià)格' + childrenMovie.getPrice().getCharge(10)); System.out.println('普通影片租賃10天的積分' + regularMovie.getPrice().getIntegral(10)); System.out.println('最新影片租賃10天的積分' + newReleaseMovie.getPrice().getIntegral(10)); System.out.println('兒童影片租賃10天的積分' + childrenMovie.getPrice().getIntegral(10)); }}

寫一 junit 測(cè)試類運(yùn)行 class Customer 的 consume() 方法。

package com.qujingbo.movie; import junit.framework.TestCase; /** * <p/> Title:junit測(cè)試類 * </p> * <p/> Description: * </p> * <p/> Date:2006-10-14 19:32:57 * </p> * * @author EOMS 曲靜波 * @version 1.0 */ public class CustomerTest extends TestCase { private Customer customer = null ; protected void setUp() throws Exception { super .setUp(); customer = new Customer(); } protected void tearDown() throws Exception { super .tearDown(); } /* * Test method for ’com.qujingbo.movie.Customer.consume()’ */ public void testConsume() { try { customer.consume(); } catch (MovieException e) { System.out.println( ' 沒有該類影片 ' ); } }}

OK 。結(jié)果為:

普通影片租賃 10 天的價(jià)格 14.0

最新影片租賃 10 天的價(jià)格 30.0

兒童影片租賃 10 天的價(jià)格 12.0

普通影片租賃 10 天的積分 20.0

最新影片租賃 10 天的積分 30.0

兒童影片租賃 10 天的積分 15.0

最后我要說,我們用 OO 表示的租賃過程并不完整,因?yàn)轭櫩筒灰欢ㄖ蛔赓U一部影片,而要租賃多部影片,這樣我們?nèi)鄙僖粋€(gè) Rental (租賃類)。而只是為說明 state pattern 替代 if else ,所以我們沒有添加 Rental (租賃類),若需要參考,請(qǐng)查閱《重構(gòu)》第一章。 點(diǎn)擊下載源碼.

到此這篇關(guān)于Java如何利用狀態(tài)模式(state pattern)替代if else的文章就介紹到這了,更多相關(guān)Java用狀態(tài)模式(state pattern)替代if else內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 苏商学院官网 - 江苏地区唯一一家企业家自办的前瞻型、实操型商学院 | 杭州中央空调维修_冷却塔/新风机柜/热水器/锅炉除垢清洗_除垢剂_风机盘管_冷凝器清洗-杭州亿诺能源有限公司 | 酶联免疫分析仪-多管旋涡混合仪|混合器-莱普特科学仪器(北京)有限公司 | 土壤养分检测仪|土壤水分|土壤紧实度测定仪|土壤墒情监测系统-土壤仪器网 | 楼梯定制_楼梯设计施工厂家_楼梯扶手安装制作-北京凌步楼梯 | 超声波电磁流量计-液位计-孔板流量计-料位计-江苏信仪自动化仪表有限公司 | 许昌奥仕达自动化设备有限公司 | 档案密集架,移动密集架,手摇式密集架,吉林档案密集架-厂家直销★价格公道★质量保证 | CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 筒瓦厂家-仿古瓦-寺庙-古建琉璃瓦-宜兴市古典园林建筑陶瓷厂有限公司 | 27PR跨境电商导航 | 专注外贸跨境电商 | 智成电子深圳tdk一级代理-提供TDK电容电感贴片蜂鸣器磁芯lambda电源代理经销,TDK代理商有哪些TDK一级代理商排名查询。-深圳tdk一级代理 | 不锈钢复合板|钛复合板|金属复合板|南钢集团安徽金元素复合材料有限公司-官网 | LED灯杆屏_LED广告机_户外LED广告机_智慧灯杆_智慧路灯-太龙智显科技(深圳)有限公司 | 代办建筑资质升级-建筑资质延期就找上海国信启航 | 不锈钢管件(不锈钢弯头,不锈钢三通,不锈钢大小头),不锈钢法兰「厂家」-浙江志通管阀 | 青岛侦探_青岛侦探事务所_青岛劝退小三_青岛调查出轨取证公司_青岛婚外情取证-青岛探真调查事务所 | 槽钢冲孔机,槽钢三面冲,带钢冲孔机-山东兴田阳光智能装备股份有限公司 | 越南专线物流_东莞国际物流_东南亚专线物流_行通物流 | 柔性输送线|柔性链板|齿形链-上海赫勒输送设备有限公司首页[输送机] | 气胀轴|气涨轴|安全夹头|安全卡盘|伺服纠偏系统厂家-天机传动 | 12cr1mov无缝钢管切割-15crmog无缝钢管切割-40cr无缝钢管切割-42crmo无缝钢管切割-Q345B无缝钢管切割-45#无缝钢管切割 - 聊城宽达钢管有限公司 | 科昊仪器超纯水机系统-可成气相液氮罐-美菱超低温冰箱-西安昊兴生物科技有限公司 | 校园文化空间设计-数字化|中医文化空间设计-党建|法治廉政主题文化空间施工-山东锐尚文化传播公司 | TPM咨询,精益生产管理,5S,6S现场管理培训_华谋咨询公司 | 流程管理|流程管理软件|企业流程管理|微宏科技-AlphaFlow_流程管理系统软件服务商 | 葡萄酒灌装机-食用油灌装机-液体肥灌装设备厂家_青州惠联灌装机械 | 考勤系统_考勤管理系统_网络考勤软件_政企|集团|工厂复杂考勤工时统计排班管理系统_天时考勤 | 上海办公室设计_办公楼,写字楼装修_办公室装修公司-匠御设计 | 天津云仓-天津仓储物流-天津云仓一件代发-顺东云仓 | 折弯机-刨槽机-数控折弯机-数控刨槽机-数控折弯机厂家-深圳豐科机械有限公司 | 非标压力容器_碳钢储罐_不锈钢_搪玻璃反应釜厂家-山东首丰智能环保装备有限公司 | 稳尚教育加盟-打造高考志愿填报平台_新高考志愿填报加盟_学业生涯规划加盟 | 超高频感应加热设备_高频感应电源厂家_CCD视觉检测设备_振动盘视觉检测设备_深圳雨滴科技-深圳市雨滴科技有限公司 | 基本型顶空进样器-全自动热脱附解吸仪价格-AutoHS全模式-成都科林分析技术有限公司 | 单级/双级旋片式真空泵厂家,2xz旋片真空泵-浙江台州求精真空泵有限公司 | 陶瓷加热器,履带式加热器-吴江市兴达电热设备厂 | 一体化净水器_一体化净水设备_一体化水处理设备-江苏旭浩鑫环保科技有限公司 | 艺术漆十大品牌_艺术涂料加盟代理_蒙太奇艺术涂料厂家品牌|艺术漆|微水泥|硅藻泥|乳胶漆 | 瓶盖扭矩测试仪-瓶盖扭力仪-全自动扭矩仪-济南三泉中石单品站 | 德国BOSCH电磁阀-德国HERION电磁阀-JOUCOMATIC电磁阀|乾拓百科 |