- 浏览: 230336 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
飞出四季做的茧:
只是转移了恶心的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 代码重构-第一章(运用多态(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 2757oyhk 学习笔记 用spring mvc 已经有一段时间 ... -
Spring Data MongoDB 去掉_class属性字段
2013-02-08 10:03 12637oyhk 学习笔记 Spring Dat ... -
springMvc 三种接收客户端参数方法
2013-02-04 12:23 2507oyhk学习笔记springMvc 三种接收客户端参数方法 ... -
spring MongoDB 集成(分页)
2013-01-26 08:42 15162oyhk 学习笔记 spring MongoDB 集成(分 ... -
spring MongoDB 集成crud操作(简单封装)
2013-01-23 08:35 7627oyhk 学习笔记 这两 ... -
elasticsearch结合spring springmvc jest 使用做成WEB架构
2013-01-17 12:16 5244oyhk 学习笔记 上一篇文章,说到了先利用jest ju ... -
elasticsearch RESTful搜索引擎-(java jest 使用[入门])
2013-01-14 10:01 21187oyhk学习笔记 elasticsearch简称ES ... -
eclispe freemarker ide 插件安装
2013-01-12 11:44 2299oyhk学习笔记 由于本网站(http://blog. ... -
elasticsearch RESTful搜索引擎-安装
2013-01-11 09:53 1811oyhk 学习笔记... 1.首先下载e ... -
elasticsearch RESTful搜索引擎-简介
2013-01-10 11:31 1683oyhk学习笔记 搜索了一些资料...关于elasti ... -
java把html标签字符转普通字符(反转换成html标签)
2013-01-09 08:28 13531oyhk 学习笔记 下面是java把html标签字符转 ... -
spring 结合 Redis 例子,简单入门例子
2013-01-07 09:25 11287oyhk 学习笔记 好了费话不多说了,介绍下sprin ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 二
2013-01-07 09:13 2977上一篇文章:java 代码重构-第一章(使用策略模式,把 ... -
java 代码重构-第一章(使用策略模式,把恶心的switch代码去掉...) 一
2013-01-06 09:49 5740上一篇文章:java 代码重构-第一章(终于…我们来到继 ... -
java 代码重构-第一章(运用多态(Polymorphism)取代与价格相关的条件逻辑)
2013-01-04 18:40 2043上一篇文章:java 代码重 ... -
java 代码重构-第一章(提炼代码)
2013-01-04 01:39 1095上篇文章说了,类做回自己的事 上一篇文章:jav ... -
java 代码重构-第一章(去除临时变量)
2013-01-04 01:33 1191上一篇文章:java 代码重 ... -
java 代码重构-第一章(类自己该做自己的事)
2012-12-30 22:19 1761重构小提示:重构技术系以微小的步伐修改程序。如果你犯下错 ... -
java 代码重构-第一章(分解并重组statement())
2012-12-28 11:34 1294上一篇文章:java 代码重构-第一章(起点) 下一篇 ... -
java 代码重构-第一章(起点)
2012-12-27 12:57 1541oyhk 学习笔记 对于重构,大家应该都一些认识了吧. ...
相关推荐
第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 为何重构 ...
《重构:改善既有代码设计》是一本由Martin Fowler所著的经典IT著作,它详细阐述了在软件开发过程中如何通过重构来提升代码质量、可读性和维护性。重构是一种系统性的方法,旨在不改变软件外在行为的前提下,改进其...
Java只支持单继承,即一个子类只能有一个直接父类,但可以通过多重继承(接口)间接实现多继承的效果。所有类默认继承自`java.lang.Object`类。 2. **多态(Polymorphism)** 多态是面向对象的三大特性之一,指的...
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的...
### CC编程指南--第10章 类的继承与组合 #### 1. 继承 (Inheritance) 在面向对象编程中,“继承”是核心概念之一,它允许创建一个新类(派生类)来继承现有类(基类或父类)的属性和行为。这一特性不仅提高了代码...
通过以上对封装、继承、覆盖、构造过程、多态以及 `static`、`this`、`super` 和 `final` 关键字的详细介绍,我们可以更好地理解和运用Java的核心概念和技术点,从而编写出更加高效、灵活和易于维护的代码。
- **继承(Inheritance)**:一个类可以继承另一个类的特性,实现代码复用。 - **多态(Polymorphism)**:同一种行为可以有不同的表现形式,通过接口或抽象类实现。 3. **异常处理**: - Java使用try-catch-...
Chapter 1:Refactoring,a First Example 重构,第一个例子 The Starting Point 起点 The First Step in Refactoring 重构第一步 Decomposing and Redistributing the Statement Method 分解并重组...
### JAVA知识整理-第一天 #### 一、Java基础概念及特性 **1.1 Java语言特点** Java是一种广泛使用的高级编程语言,具有以下显著特点: - **可靠性**:Java通过严格的类型检查、自动垃圾回收机制等特性提高了代码...
Chapter 1:Refactoring,a First Example 重构,第一个例子 The Starting Point 起点 The First Step in Refactoring 重构第一步 Decomposing and Redistributing the Statement Method 分解并重组...
本资源包"java程序代码-java开发学习之路"是为初学者精心准备的,旨在帮助初学者深入理解和实践Java开发技术。 首先,让我们从基础开始。Java的基础语法与C++相似,但更加简洁和安全。在Java中,一切皆为对象,这是...
在 Java 面向对象(Object-Oriented Programming, OOP)编程中,我们主要关注以下几个核心概念:类(Class)、对象(Object)、封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)。这些概念构成了 ...
在C++编程语言中,继承(Inheritance)是面向对象编程的一个核心概念,它允许一个类(称为子类或派生类)从另一个类(称为基类或父类)继承特性。这种特性使得代码重用变得简单,同时也能实现多态性。"inheritance--...
1. 代码坏味道的识别与处理:这是重构的第一步,需要识别代码中不健康的模式(即“坏味道”),如冗余代码、过长的方法、过大的类等。一旦识别出来,可以采用特定的重构手法来改善这些问题。 2. 提炼方法(Extract ...
4. **继承(Inheritance)**:Java支持单一继承,一个类可以继承另一个类的属性和方法,从而实现代码复用和多态性。 5. **接口(Interface)**:接口是完全抽象的类,只能包含常量和抽象方法。Java8引入了默认方法...
本节内容主要围绕“Java语言程序设计_第4章_类的重用”展开,通过“第4章 类的重用(熊).ppt”的课件和源代码,我们将深入探讨这个主题。 首先,类的重用主要体现在两个方面:继承(Inheritance)和接口...
### Java语言程序设计基础第十版第十一章课后复习题答案解析 #### 11.1 关于子类与父类的关系 - **题目**: 下面说法是真是假?一个子类是父类的子集。 - **答案**: 假,子类是父类的扩展,并不是子集。 - **解析**:...
在Java编程语言中,封装、继承和多态是面向对象编程的三大核心概念,它们为构建复杂的软件系统提供了坚实的基础。下面将详细讲解这些概念及其重要性。 **封装**是面向对象编程的基本原则之一,它涉及到将数据和操作...