- 浏览: 227772 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
飞出四季做的茧:
只是转移了恶心的switch吧,并没有去除掉
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一 -
niqingyang:
https://www.cnblogs.com/xueduan ...
百度搜索url编码解密(url encode decode) -
niqingyang:
function urldecode(str, charset ...
百度搜索url编码解密(url encode decode) -
ttdeye:
private Jedis getJedis(){if(jed ...
spring 结合 Redis 例子,简单入门例子 -
adair_java:
最近手机baidu,搜索关键字编码好像加密了比如这个:http ...
各搜索引擎referer关键字,编码
java 代码重构-第一章(终于…我们来到继承(Inheritance))
- 博客分类:
- java
上一篇文章:java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
下一篇文章:java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
终于……我们来到继承(Inheritance)
我们有数种影片类型,它们以不同的方式回答相同的问题。这听起来很像subclasses 的工作。我们可以建立Movie 的三个subclasses ,每个都有自己的计费法(图1.14)。
这么一来我就可以运用多态(polymorphism)来取代switch 语句了。很遗憾的是这里有个小问题,不能这么干。一部影片可以在生命周期内修改自己的分类,一个对象却不能在生命周期内修改自己所属的class。不过还是有一个解决方法:State pattern(模式)[Gang of Four]。运用它之后,我们的classes 看起来像图1.15。
加入这一层间接性,我们就可以在Price 对象内进行subclassing 动作(译注:一如图1.15),于是便可在任何必要时刻修改价格。
如果你很熟悉Gang of Four 所列的各种模式(patterns),你可能会问:『这是一个State 还是一个Strategy?』答案取决于Price class 究竟代表计费方式(此时我喜欢把它叫做Pricer 或PricingStrategy),或是代表影片的某个状态(state,例如「Star Trek X 是一部新片」)。在这个阶段,对于模式(和其名称)的选择反映出你对结构的想法。此刻我把它视为影片的某种状态(state)。如果未来我觉得Strategy 能更好地说明我的意图,我会再重构它,修改名字,以形成Strategy 。
为了引入State 模式,我使用三个重构准则。首先运用Replace Type Code with State/Strategy,将「与型别相依的行为」(type code behavior )搬移至State 模式内。然后运用Move Method 将switch 语句移到Price class 里头。最后运用Replace Conditional with Polymorphism去掉switch 语句。
首先我要使用Replace Type Code with State/Strategy。第一步骤是针对「与 型别相依的行为」使用Self Encapsulate Field,确保任何时候都通过getting 和setting 两个函数来运用这些行为。由于多数代码来自其他classes,所以多数函数都己经使用getting 函数。但构造函数(constructor )仍然直接访问价格代号(译注:程序中的priceCode):
public Movie(String title, int priceCode) { this.title = title; this.priceCode = priceCode; }
然后编译并测试,确保没有破坏任何东西。
输出结果:
Rental Record for oyhk 少林足球 6.0 大话西游 1.5 Amount owed is 7.5 You earned 3 frequent renter points ------------------------------------------------ <H1>Rentals for <EM>oyhk</EM></ H1><P> 少林足球: 6.0<BR> 大话西游: 1.5<BR> <P>You owe <EM>7.5</EM><P> On this rental you earned <EM>3</EM> frequent renter points<P>
证明重构没有错,结果跟上次的一样
下面是完整的代码:
Movie
package com.mkfree.refactoring.shap1; /** * 电影类 * * @author hk * * 2012-12-25 下午10:55:14 */ public class Movie { public static final int CHILDRENS = 2; public static final int REGULAR = 0; public static final int NEW_RELEASE = 1; public Movie(String title, int priceCode) { this.title = title; this.priceCode = priceCode; } private String title; private int priceCode; public String getTitle() { return title; } public int getPriceCode() { return priceCode; } /** * 获取收费 * * @param daysRented * @return */ double getCharge(int daysRented) { double result = 0; switch (getPriceCode()) { case Movie.REGULAR: result += 2; if (daysRented > 2) result += (daysRented - 2) * 1.5; break; case Movie.NEW_RELEASE: result += daysRented * 3; break; case Movie.CHILDRENS: result += 1.5; if (daysRented > 3) result += (daysRented - 3) * 1.5; break; } return result; } int getFrequentRenterPoints(int daysRented) { if ((getPriceCode() == Movie.NEW_RELEASE) && daysRented > 1) return 2; else return 1; } }
Rental
package com.mkfree.refactoring.shap1; /** * 租凭 * * @author hk * * 2012-12-25 下午10:57:00 */ 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; } /** * 把代码迁移到movie中 * * @return */ double getCharge() { return this.getMovie().getCharge(daysRented); } /** * 获取经常的租赁 * * @return */ int getFrequentRenterPoints() { return this.getMovie().getFrequentRenterPoints(daysRented); } }
Customer
package com.mkfree.refactoring.shap1; import java.util.Enumeration; import java.util.Vector; /** * 顾客 * * @author hk * * 2012-12-25 下午10:59:03 */ public class Customer { private String name; private Vectorrentals = new Vector<>(); public Customer(String name) { this.name = name; } /** * 添加 * * @param rental */ public void addRentals(Rental rental) { rentals.add(rental); } public String getName() { return name; } /** * 通计清单 * * @return */ public String statement() { Enumerationenu_rentals = rentals.elements(); String result = "Rental Record for " + this.getName() + " \n"; while (enu_rentals.hasMoreElements()) { Rental each = enu_rentals.nextElement(); result += "\t" + each.getMovie().getTitle() + "\t" + String.valueOf(each.getCharge()) + "\n"; } result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n"; result += "You earned " + String.valueOf(getTotalFrequentRenterPoints()) + " frequent renter points"; return result; } // 此即所谓query method private double getTotalCharge() { double result = 0; Enumerationenu_rentals = rentals.elements(); while (enu_rentals.hasMoreElements()) { Rental each = (Rental) enu_rentals.nextElement(); result += each.getCharge(); } return result; } // 此即所谓query method private int getTotalFrequentRenterPoints() { int result = 0; Enumerationenu_rentals = rentals.elements(); while (enu_rentals.hasMoreElements()) { Rental each = (Rental) enu_rentals.nextElement(); result += each.getFrequentRenterPoints(); } return result; } }
Client
package com.mkfree.refactoring.shap1; import org.junit.Test; public class Client { @Test public void testStatement() { Movie movie1 = new Movie("少林足球", 1); Rental rental1 = new Rental(movie1, 2); Movie movie2 = new Movie("大话西游", 2); Rental rental2 = new Rental(movie2, 3); Customer customer = new Customer("oyhk"); customer.addRentals(rental1); customer.addRentals(rental2); String statement = customer.statement(); System.out.println(statement); System.out.println("------------------------------------------------"); String htmlStatment = customer.htmlStatement(); System.out.println(htmlStatment); } }
由于重构了Movie代码,对于Client当然也修改了一点点了...
本文章来自:http://blog.mkfree.com/posts/28
发表评论
-
springMvc 注解配置例子(hello world)
2013-02-21 10:53 2704oyhk 学习笔记 用spring mvc 已经有一段时间 ... -
Spring Data MongoDB 去掉_class属性字段
2013-02-08 10:03 12546oyhk 学习笔记 Spring Dat ... -
springMvc 三种接收客户端参数方法
2013-02-04 12:23 2460oyhk学习笔记springMvc 三种接收客户端参数方法 ... -
spring MongoDB 集成(分页)
2013-01-26 08:42 15074oyhk 学习笔记 spring MongoDB 集成(分 ... -
spring MongoDB 集成crud操作(简单封装)
2013-01-23 08:35 7565oyhk 学习笔记 这两 ... -
elasticsearch结合spring springmvc jest 使用做成WEB架构
2013-01-17 12:16 5189oyhk 学习笔记 上一篇文章,说到了先利用jest ju ... -
elasticsearch RESTful搜索引擎-(java jest 使用[入门])
2013-01-14 10:01 21122oyhk学习笔记 elasticsearch简称ES ... -
eclispe freemarker ide 插件安装
2013-01-12 11:44 2258oyhk学习笔记 由于本网站(http://blog. ... -
elasticsearch RESTful搜索引擎-安装
2013-01-11 09:53 1758oyhk 学习笔记... 1.首先下载e ... -
elasticsearch RESTful搜索引擎-简介
2013-01-10 11:31 1631oyhk学习笔记 搜索了一些资料...关于elasti ... -
java把html标签字符转普通字符(反转换成html标签)
2013-01-09 08:28 13472oyhk 学习笔记 下面是java把html标签字符转 ... -
spring 结合 Redis 例子,简单入门例子
2013-01-07 09:25 11238oyhk 学习笔记 好了费话不多说了,介绍下sprin ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
2013-01-07 09:13 2931上一篇文章:java 代码重构-第一章(使用策略模式,把 ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
2013-01-06 09:49 5650上一篇文章:java 代码重构-第一章(终于…我们来到继 ... -
java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
2013-01-04 18:40 1987上一篇文章:java 代码重 ... -
java 代码重构-第一章(提炼代码)
2013-01-04 01:39 1010上篇文章说了,类做回自己的事 上一篇文章:jav ... -
java 代码重构-第一章(去除临时变量)
2013-01-04 01:33 1100上一篇文章:java 代码重 ... -
java 代码重构-第一章(类自己该做自己的事)
2012-12-30 22:19 1673重构小提示:重构技术系以微小的步伐修改程序。如果你犯下错 ... -
java 代码重构-第一章(分解并重组statement())
2012-12-28 11:34 1204上一篇文章:java 代码重构-第一章(起点) 下一篇 ... -
java 代码重构-第一章(起点)
2012-12-27 12:57 1460oyhk 学习笔记 对于重构,大家应该都一些认识了吧. ...
相关推荐
第1章 重构,第一个案例 1 1.1 起点 1 1.2 重构的第一步 7 1.3 分解并重组statement() 8 1.4 运用多态取代与价格相关的条件逻辑 34 1.5 结语 52 第2章 重构原则 53 2.1 何谓重构 53 2.2 为何重构 ...
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
Chapter 1:Refactoring,a First Example 重构,第一个例子 The Starting Point 起点 The First Step in Refactoring 重构第一步 Decomposing and Redistributing the Statement Method 分解并重组...
Chapter 1:Refactoring,a First Example 重构,第一个例子 The Starting Point 起点 The First Step in Refactoring 重构第一步 Decomposing and Redistributing the Statement Method 分解并重组...
Laravel开发-laravel-single-table-inheritance 包含单表继承模型的包,具有雄辩(laravel orm)
Laravel开发-eloquent-single-table-inheritance 单表继承(Sti)作为Laravel雄辩模型的特征实现
Basic manual of java for beginners with simple and easy descriptions. Inheritance, composition, collections, files, interfaces
一个很强大的工具, 能将c#代码片段、文件甚至工程直接转换成java代码,并能彻底解决外部引用的DLL问题,最强的是支持c#工程的直接转换,生成的Java代码质量也很不错。软件已破解,去除了未注册版最多只能转换1000行的...
java-abstraction-inheritance:一个简单的Java控制台程序,使用抽象和继承的概念
Java-Inheritance-Assignment-2
第一章 瞭解 Java 第二章 入門準備 第三章 語法入門 第四章 瞭解 Java 第五章 陣列 第六章 字串 第七章 封裝(Encapsulation) 第八章 繼承(Inheritance)、多型(Polymorphism) 第九章 管理類別檔案 第十章 例外...
介绍Java的封装继承和多态和java的一些基本特性
继承(inheritance)是Java OOP中一个非常重要的概念。这篇文章主要介绍了JAVA基础之继承(inheritance),需要的朋友可以参考下
继承的访问控制 马克-to-win java视频 inheritance access
继承的访问控制 马克-to-win java视频 inheritance access
Laravel开发-single-table-inheritance 单表继承特性
Java 核心技术 卷1 Index Chapter 1: An Introduction to Java 1 Java As a Programming Platform 2 The Java “White Paper” Buzzwords 2 Java Applets and the Internet 7 A Short History of Java 9 ...