名词:类型码 类型码的上层建筑 重构方法 1.使用子类代替类型码 2.使用状态/策略模式代替类型码

类中存在方法把某个字段当作条件,根据字段值的不同,进行不同的处理。(自定义概念)
则这个字段叫做:类型码。(重构-改善既有代码的设计中的概念)
这个方法叫做:类型码的上层建筑。(自定义概念)
(这种判断方法不是绝对正确,但是一般可行,类型码是重构-改善既有代码的设计的概念,但是类型码的上层建筑是自定义概念) 例子1:
Movie对象中存在影片类型字段,根据影片类型和租期计算金额的getCharge()方法和计算用户积分的getRentPoints()
getCharge()方法和getRentPoints()都以影片类型字段为条件,进行不同的处理。
所以根据上面的解释:
类型码=影片类型
类型码(影片类型)的上层建筑2个:getCharge()方法和getRentPoints()方法
 package refactor;

 public class Movie {
public static final int NEW_RELEASE = 0;
public static final int REGULAR = 1;
public static final int CHILDREN = 2; private int priceCode;
private String title; public Movie() {
} public Movie(String title, int priceCode) {
this.priceCode = priceCode;
this.title = title;
} public double getCharge(int daysRent){
double result = 0;
switch(priceCode){
case Movie.REGULAR:
result += 2;
if(daysRent > 2){
result += (daysRent - 2) * 1.5;
}
break;
case Movie.NEW_RELEASE:
result += daysRent * 3;
break;
case Movie.CHILDREN:
result += 1.5;
if(daysRent > 3){
result += (daysRent - 3) * 1.5;
}
break;
}
return result;
} public int getRentPoints(int daysRent){
int rentPoints = 1;
if(priceCode == Movie.NEW_RELEASE
&& daysRent > 1){
rentPoints++;
}
return rentPoints;
}
}

Movie直接使用类型码

当影片类型不多,分支逻辑不复杂,上层建筑不多,并且以后变化也不大时,直接使用类型码和使用多态重构区别不太大。

直接使用类型码的问题:
可是随着影片类型的迅速扩张,分支逻辑的复杂性升高,上层建筑的增多,直接使用类型码将导致
1.如果影片类型增加的非常多时,则条件语句将会非常长,并且每个上层建筑都会对应一个这样的条件语句。
2.如果影片类型增加,上层建筑增多,而此时分支逻辑复杂度也很高,则需要为了防止上层建筑过长,需要抽取每个分支逻辑为方法,将可能导致本类方法迅速膨胀。
所以:当影片类型,分支逻辑,上层建筑发生的变化较大时,则直接使用类型码会导致类过大,上层建筑过长或者产生过多的方法,条件语句随着上层建筑重复等问题,
总之就是导致代码难逻辑和结构的越来越不清晰,越来越难理解,越来越难修改,越来越容易出错。 使用重构则是较好的解决方案:
1.replace type code with subclass 对象类型码的值在生命期间不会发生变化
2.replace type code with state/strategy 对象类型码的值可能在生命期间发生变化。
好处:
1.不管原来的上层建筑有多少,重构后,只需要维护一个产生子类或者状态/策略的条件语句。
2.与类型码相关的处理都被放到相应的类中。代码结构和逻辑更清晰。
每个子类(状态/策略)与类型码的值一一对应,每个与类型码值对应的处理逻辑都被放在与该类型码值相对应的子类(状态/策略)中,代码的结构和逻辑非常清晰。
每个子类(状态/策略)与类型码的值一一对应,每个与类型码值对应的处理逻辑都被放在与该类型码值相对应的子类(状态/策略)中,代码的结构和逻辑非常清晰。
每个子类(状态/策略)与类型码的值一一对应,每个与类型码值对应的处理逻辑都被放在与该类型码值相对应的子类(状态/策略)中,代码的结构和逻辑非常清晰。
 
 package shop;

 public class Movie {
public static final int NEW_RELEASE = 0;
public static final int REGULAR = 1;
public static final int CHILDREN = 2; private String title;
private Price price; public Movie() {
} public Movie(String title, int priceCode) {
setPriceCode(priceCode);
this.title = title;
} public int getPriceCode() {
return price.getPriceCode();
} //有2个上层建筑,但是程序只需要维护一个根据类型码产生state对象的条件语句
public void setPriceCode(int priceCode) {
switch (priceCode){
case Movie.NEW_RELEASE:
price = new NewPrice();
break;
case Movie.REGULAR:
price = new RegularPrice();
break;
case Movie.CHILDREN:
price = new ChildrenPrice();
break;
default:
throw new IllegalArgumentException("非法的影片类型:" + priceCode);
}
} public double getCharge(int daysRent){
return price.getCharge(daysRent);
} public int getRentPoints(int daysRent){
return price.getRentPoints(daysRent);
}
}

Movie使用状态模式重构类型码

 package shop;
//子类或状态与类型码一一对应,相应的逻辑也全部集中在这个类中。代码的结构和逻辑更清晰
public class ChildrenPrice extends Price {
@Override
public int getPriceCode(){
return Movie.CHILDREN;
} @Override
public double getCharge(int daysRent) {
double result = 1.5;
if(daysRent > 3){
result += (daysRent - 3) * 1.5;
}
return result;
}
}

ChildrenPrice子类或状态与类型码一一对应

 package shop;
//子类或状态与类型码一一对应,相应的逻辑也全部集中在这个类中。代码的结构和逻辑更清晰
public class NewPrice extends Price{
@Override
public int getPriceCode() {
return Movie.NEW_RELEASE;
} @Override
public double getCharge(int daysRent) {
return daysRent * 3;
} @Override
public int getRentPoints(int daysRent) {
return daysRent > 1 ? 2 : 1;
}
}

NewPrice 子类或状态与类型码一一对应

 package shop;
//子类或状态与类型码一一对应,相应的逻辑也全部集中在这个类中。代码的结构和逻辑更清晰
public class RegularPrice extends Price {
@Override
public int getPriceCode() {
return Movie.REGULAR;
} @Override
public double getCharge(int daysRent) {
double result = 2;
if(daysRent > 2){
result += (daysRent - 2) * 1.5;
}
return result;
}
}

RegularPrice 子类或状态与类型码一一对应

类型码:类的一个字段,该类中存在方法把这个字段当作条件,根据字段值的不同,进行不同的处理。
类型码的上层建筑:某个方法,根据类型码不同的值进行不同处理。
当类型码的上层建筑有多个,则每个上层建筑都需要维护着条件判断。导致总体上基于类型码的条件判断有多个。
重构方法:
1.replace type code with subclass
2.replace type code with state/strategy
和直接使用类型码的区别:
2个重构手法避免了多个基于类型码的条件判断的产生,使基于类型码的条件判断始终只有一个。
上层建筑通过多态

重构学习day01 类型码 类型码的上层建筑 与类型码相关的重构方法 1.使用子类代替类型码 2.使用状态或策略模式代替类型码的更多相关文章

  1. Python策略模式实现源码分享

    1.让一个对象的某个方法可以随时改变,而不用更改对象的代码 2.对于动态类型的Python语言,不需要定义接口 3.基本的实现方法:用类作为参数传递 例如: 12_eg3.py class Movea ...

  2. java学习day01之String的特点,如何实现,并且有哪些重要方法?

    1.以主流的JDK版本1.8来说,String内部实际存储结构为char数组,源码如下: public final class String  implements java.io.Serializa ...

  3. 第三百四十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—爬虫和反爬的对抗过程以及策略—scrapy架构源码分析图

    第三百四十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—爬虫和反爬的对抗过程以及策略—scrapy架构源码分析图 1.基本概念 2.反爬虫的目的 3.爬虫和反爬的对抗过程以及策略 scra ...

  4. 使用策略模式重构switch case 代码

    目录 1.背景 2.案例 3.switch…case…方式实现 4.switch…case…带来的问题 5.使用策略模式重构switch…case…代码 6.总结 1.背景 之前在看<重构    ...

  5. swift设计模式学习 - 策略模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 策略模式 策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. ...

  6. 项目一:第五天 1、区域数据(pinyin4j-简码,城市编码) 2、Web层代码重构(model对象,分页代码提取) 3、区域分页查询 3、分区添加功能 4、定区管理管理-添加,分页

    Service: /** * @Description: 1.保存定区  2.让分区关联定区 * 对象三种状态 1.持久态(被session管理对象-一级缓存中有对象) 2.托管态(有OID标识,数据 ...

  7. Future模式的学习以及JDK内置Future模式的源码分析

    并发程序设计之Future模式 一).使用Future模式的原因 当某一段程序提交了一个请求,期待得到一个答复,但服务程序对这个请求的处理可能很慢,在单线程的环境中,调用函数是同步的,必须等到服务程序 ...

  8. 与众不同 windows phone (24) - Input(输入)之软键盘类型, XNA 方式启动软键盘, UIElement 的 Touch 相关事件, 触摸涂鸦

    原文:与众不同 windows phone (24) - Input(输入)之软键盘类型, XNA 方式启动软键盘, UIElement 的 Touch 相关事件, 触摸涂鸦 [索引页][源码下载] ...

  9. Netty-主从Reactor多线程模式的源码实现

    Netty--主从Reactor多线程模式的源码实现 总览 EventLoopGroup到底是什么? EventLoopGroup是一个存储EventLoop的容器,同时他应该具备线程池的功能. gr ...

随机推荐

  1. (非原)SQL注入专题--整理帖 && like 语句拼sql 如何防止注入攻击。

    原地址:blog.csdn.net/lvjin110/article/details/28697695 like 语句拼sql 如何防止注入攻击?http://bbs.csdn.net/topics/ ...

  2. Linux就该这么学--命令集合3(文本文件编辑命令)

    1.cat命令查看纯文本文件(较短):(cat [选项] [文件]) cat -n showpath.sh 附录: -n 显示行号 -b 显示行号(不包括空行) -A 显示出“不可见”的符号,如空格, ...

  3. Post Man 调用CRMAPI

    官方文档 https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/webapi/setup-postman ...

  4. css 浏览器兼容性问题集合

    http://www.xidayun.com/index.php/2016/05/16/941/ 文章取自前端蜂小客

  5. hdu-5621 KK's Point(dp+数学)

    题目链接: KK's Point Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others ...

  6. Java操作系统硬件的方法Unsafe

    通常Java代码都是运行在JVM中而不能直接访问系统硬件如进行内存分配释放等,但如果有需要跳过JVM直接用Java访问系统硬件,比如像C语言指针一样操作的话就可以调用Unsafe对象相关方法. 1.U ...

  7. Linux 终端显示 Git 当前所在分支

    function git_branch { branch="`git branch 2>/dev/null | grep "^\*" | sed -e " ...

  8. HDU1171(01背包均分问题)

    Big Event in HDU Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u De ...

  9. 机器学习之逻辑回归(logistic回归)

    前言            以下内容是个人学习之后的感悟,转载请注明出处~ 逻辑回归 一.为什么使用logistic回归   一般来说,回归不用在分类问题上,因为回归是连续型模型,而且受噪声影响比较大 ...

  10. 利用PDF.JS插件解决了本地pdf文件在线浏览问题(根据需要隐藏下载功能,只保留打印功能)

    我是在IE11和谷歌上做的测试,都可以显示,把做出的东西记录下来,方便大家还有自己学习! 可以在IIS7服务器上也可以下载Tomcat来做服务器 Tomcat下载地址   http://pan.bai ...