当前位置: 首页 > 编程日记 > 正文

必会重构技巧:使用多态替换条件

使用多态替换条件:指在进行类型检查和执行某些类型操作时,最好将算法封装在类中,并且使用多态来对代码中的调用进行抽象

举例理解:看定义可能比较迷糊,其实说的简单一点,对于使用分支语句并且分支条件是和类型检查相关的程序段,如 if(type == typeof(TypeA)){...}else if(type == typeof(TypeB)){...},可以把{...}中的Code,尝试放到if的条件中去。然后通过检查Type就可以直接返回需要的东东了,这样做可以利用已有的继承层次进行计算,比较便于维护。如果还是觉得说的太抽象,可以看看下面的代码感觉一下。

项目实例:用WPF做一个网游的客户端Demo,里面需要对商品,邮件,物品栏做分页操作。于是手动写了几个分页的类。开始是把分页的计算方法都写在了事件里面的,每一个Button绑定一个事件,每次需要修改或者使用分页的时候,都要找到相关类进行修改,复制,各个方法的耦合程度大增,程序可读性,复用性和可维护性都不太好。虽然这个项目是很久之前做的了,但这里既然想起来了,觉得还是可以尝试用这种重构方法,效果如何大家自己看看吧。
  先来看看原始的未经过重构的代码:

ContractedBlock.gifExpandedBlockStart.gif原始代码
//x:目标页数索引值 y:每页显示记录个数 这里不Care你是如何取到这几个值的和对这两个Int值合法性的验证
protected void btnFirstPage_Click(object sender, EventArgs e)
{
Button btn
= sender as Button;
if (btn != null)
{
repDataList.DataSource
= Getdata(x,y); //Get Date from DB
}
}
protected void btnPrePage_Click(object sender, EventArgs e)
{
Button btn
= sender as Button;
if (btn != null)
{
repDataList.DataSource
= Getdata(x, y); //Get Date from DB
}
}
protected void btnNextPage_Click(object sender, EventArgs e)
{
Button btn
= sender as Button;
if (btn != null)
{
repDataList.DataSource
= Getdata(x, y); //Get Date from DB
}
}
protected void btnlastPage_Click(object sender, EventArgs e)
{
Button btn
= sender as Button;
if (btn != null)
{
repDataList.DataSource
= Getdata(x, y); //Get Date from DB
}
}
private DataSet Getdata(int targetPageIndex, int numberPerPage) //Get Date from DB
{
throw new NotImplementedException(); //Here some code to retrive Data from DB
}

上面的几段代码可以实现功能,但是却存在以下几点问题。
(1)如果有多个页面需要使用分页,同样的代码需要复制多次,复用性差
(2)第一个问题造成了第二个问题,如果需要修改某段方法,那所有的相关页面都要修改,可维护性差
(3)相似逻辑的方法写在了多个事件中,可读性差
为了解决这三个问题,现在重构后的代码如下:
ContractedBlock.gifExpandedBlockStart.gif重构后
public abstract class Paging
{
public int TargetPageIndex { get; set; }
public int NumberPerPage { get; set; }
public abstract DataSet DataList { get; }
}
public class FirstPage : Paging
{
public FirstPage(int targetPageIndex, int numberPerPage)
{
TargetPageIndex
= targetPageIndex;
NumberPerPage
= numberPerPage;
}
public override DataSet DataList
{
get
{
return Getdata(TargetPageIndex, NumberPerPage);
}
}
}
public class PrePage : Paging
{
public PrePage(int targetPageIndex, int numberPerPage)
{
TargetPageIndex
= targetPageIndex;
NumberPerPage
= numberPerPage;
}
public override DataSet DataList
{
get
{
return Getdata(TargetPageIndex, NumberPerPage);
}
}
}
public class NextPage : Paging
{
public NextPage(int targetPageIndex, int numberPerPage)
{
TargetPageIndex
= targetPageIndex;
NumberPerPage
= numberPerPage;
}
public override DataSet DataList
{
get
{
return Getdata(TargetPageIndex, NumberPerPage);
}
}
}
public class LastPage : Paging
{
public LastPage(int targetPageIndex, int numberPerPage)
{
TargetPageIndex
= targetPageIndex;
NumberPerPage
= numberPerPage;
}
public override DataSet DataList
{
get
{
return Getdata(TargetPageIndex, NumberPerPage);
}
}
}

以上代码可以独立出一个Paging的类,略加修改就可以对应任意的DataSource。
ContractedBlock.gifExpandedBlockStart.gif前台调用代码
protected void btnPaging_Click(object sender, EventArgs e)
{
Button btn
= sender as Button;
if (btn == null) return;
Paging page;
switch (btn.CommandArgument)
{
case "FirstPage":
page
= new FirstPage(x,y);
repDataList.DataSource
= page.DataList;
break;
case "PrePage":
page
= new PrePage(x, y);
repDataList.DataSource
= page.DataList;
break;
case "NextPage":
page
= new NextPage(x, y);
repDataList.DataSource
= page.DataList;
break;
case "LastPage":
page
= new LastPage(x, y);
repDataList.DataSource
= page.DataList;
break;

}
}

个人感觉,对于本例中的应用,好处并不是很明显,也许是我写的有问题,也许是我选择例子有问题。尽管如此,重构的思想体现出来了,那就是把算法封装到多态中。此种重构在对于含类型判断条件的复杂算法分支的应用上,效果还是比较显著的。

转载于:https://www.cnblogs.com/dongpo888/archive/2010/07/13/1776674.html

相关文章:

深度分析Java的枚举类型——枚举的线程安全性及序列化问题

点击关注,快速进阶高级架构师作者:Hollis写在前面:Java SE5提供了一种新的类型-Java的枚举类型,关键字enum可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是…

1081 Rational Sum 有理数类型题处理 需再做

一、有理数结构体的几个约束 struct fraction{LL up,down;fraction(LL _up,LL _down):up(_up),down(_down){} }; (1)如果这个有理数是0,则让分子为0,分母为1(这方便后来输出时归于整数一类) (2)如果这个…

LeetCode 191 Number of 1 Bits

LeetCode 191 Number of 1 Bits 解法一(较为传统都解法):使用将n不断右移,并与1想&得到1的个数;(也有使用除法/2的,明显除法的运行效率要低于位移) 时间复杂度:0(logn) 1 int hammingWeight(uint32_t …

某网站破解备忘

某网站采用了多种反破解手段,特此开贴记录分析破解过程。 工具和参考 awesome-java-crawler - 我收集的爬虫相关工具和资料 java-curl - 本人写的java HTTP库,可用来替换chrome网络后端,更方便控制底层行为,如缓存、代理、监控、修…

用XML反序列化快速完成ASP.NET配置文件

一般来说&#xff0c;asp.net的配置文件用web.config就可以解决&#xff0c;但是有时候我们希望完全用自己的形式来配置某些东西&#xff0c;比如希望用下面的形式来配置一个站点的所有有message。<Messages> <Message ID"ID1">Message1</Message&…

1088 Rational Arithmetic

本题需要具备有理数处理相关知识。 本次收获(错点) &#xff08;1&#xff09;在化简求最大公约数时&#xff0c;忘记给传入的分子加绝对值 &#xff08;2&#xff09;把除法错写成乘法&#xff0c;自己设计测试用例才测出orz AC代码 #include<cstdio> #include<…

CesiumLab V1.2 新功能 倾斜数据处理

一转眼又是一周的时间&#xff0c;我们的实验室功能又强大了。 照旧我们先放毒&#xff0c;放图&#xff0c;图&#xff0c;太晚了&#xff0c;字都敲不到一起了lod以及包围盒大雁塔实例&#xff0c;按楼层单体化倾斜数据处理参数设置 简单介绍一下 CesiumLab 的 Osgb倾斜数据转…

参加海峡两岸城市地理信息系统论坛2010 年会(一张图、规划信息化和空间句法的碎碎念)...

上周末去清华建筑学院开了个会&#xff0c;叫做海峡两岸城市地理信息系统论坛2010 年会&#xff0c;主题很大&#xff0c;但是内容比较集中一些&#xff0c;就是围绕着GIS与城市规划。一天下来听了20个报告&#xff0c;挺佩服主办方的时间控制&#xff0c;这么密集的报告&#…

hdu 2087 剪花布条

http://acm.hdu.edu.cn/showproblem.php?pid2087 水题&#xff0c;注意细节就可以了。 代码如下&#xff1a; #include<iostream> #include<string>using namespace std;int main() {string s1,s2;while(cin>>s1&&s1!"#"){cin>>s2;…

感知机模拟或门的实现:权重和阈值的设置

def orGate(x1, x2):w1, w2, theta 0.5, 0.5, 0.4tmp x1 * w1 x2 * w2if tmp < theta:return 0elif tmp > theta:return 1print(orGate(1, 1)) print(orGate(0, 1)) print(orGate(1, 0)) print(orGate(0, 0))

apply call bind 简介

Function.prototype.call(thisArg [, arg1, arg2, ...]) call() 简述 call() 方法 调用一个函数, 其具有一个指定的 this 值和分别地提供的参数(参数的列表)。当第一个参数为 null、undefined 的时候&#xff0c; 默认 this 上下文指向window。call() 简单实例 const name qia…

自定义控件的构建(5)

Share 在ASP.NET框架中支持在回传中保存值的有2种方式&#xff1a;视图状态和控件状态 视图状态 ASP.NET中几个对象属性与控件最为密切的&#xff0c;就是ViewState了。 这里对其做下说明&#xff0c;任何可序列化类的实例均可添加到视图状态中&#xff0c;但是实际上&#xff…

Javascript之旅——第一站:从变量说起

原文出处&#xff1a; 一线码农的博客 欢迎分享原创到伯乐头条 工作这几年&#xff0c;js学的不是很好&#xff0c;正好周末有些闲时间&#xff0c;索性买本《js权威指南》&#xff0c;大名鼎鼎的犀牛书&#xff0c;好好的把js深入的看一看。买过这本书的第一印象就是贼厚&am…

从浏览器发展史读懂user-agent

世界上第一个浏览器&#xff1a;WorldWideWeb(和万维网重名)&#xff0c;改名Nexus&#xff0c;只能在NeXT系统运行。 世界上第二个浏览器&#xff1a;Line Mode Browser&#xff0c;C语言编写&#xff0c;只能显示文本&#xff0c;可以移植到不同系统。 世界上第三个浏览器(…

在把 png 或者 gif“储存为 web 所用格式”时,勾选“交错”选项

选择“交错”可创建在整个图像文件的下载过程中&#xff0c;在浏览器中以低分辨率显示的图像。“交错”可以使下载时间显得较短&#xff0c;并使查看者确信下载正在进行。但是交错也会增大文件大小。转载于:https://www.cnblogs.com/dongzhiquan/archive/2010/07/28/1994585.ht…

学习GraphX

首先准备如下社交图形数据&#xff1a;打开spark-shell&#xff1b;导入相关包&#xff1a;import org.apache.spark._ import org.apache.spark.graphx._ import org.apache.spark.rdd.RDD创建如上graph对象&#xff1a;// Create an RDD for the vertices val users: RDD[(Ve…

安装NodeJS环境报错

Failures - (exited 1) - Error while running C:\ProgramData\chocolatey\lib\visualstudio2019-workload-vctools\tools\ChocolateyInstall.ps1. 待解决

Eureka单机高可用伪集群配置

Eureka Server高可用集群理论上来讲&#xff0c;因为服务消费者本地缓存了服务提供者的地址&#xff0c;即使Eureka Server宕机&#xff0c;也不会影响服务之间的调用&#xff0c;但是一旦新服务上线&#xff0c;已经缓存在本地的服务提供者不可用了&#xff0c;服务消费者也无…

小小21点模拟

#include<iostream> #include<string> #include<cstdlib> #include<ctime> using namespace std; struct Card //一张扑克牌 { int value; //点数 string color; //花色 string face; //1-10、J、Q、K面值 }; void initCards(Card *cards) { for(int i…

BZOJ-1005 明明的烦恼

Prufer编码练习题&#xff0c;这个编码是跟树的生成计数有关系的。 推荐这篇博文&#xff1a;http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html 介绍地挺全面生动形象 会了Prufer之后这道题还要用上组合数学来高精度计算。 #include <cstdlib> #in…

使用npm打包后生成的package.json中重要字段含义

{"name": "demo",// 包名称,不能和npm平台上其他包重复"version": "1.0.0",// 版本号"description": "","main": "index.js",// 执行入口"scripts": {// 自定义脚本"test&quo…

Winform窗体应用程序的自动更新功能

本文将演示一种桌面程序自动更新方案&#xff0c;其步骤比较多&#xff0c;但原理非常简单&#xff0c;通用性尚可&#xff0c;对于小型应用来说&#xff0c;直接拿去就可以用了。原理服务器端的结构是这样的&#xff1a;其工作原理如下&#xff1a;Update.asmx 仅提供一个功能…

[UWP] 用 AudioGraph 来增强 UWP 的音频处理能力——AudioFrameInputNode

原文:[UWP] 用 AudioGraph 来增强 UWP 的音频处理能力——AudioFrameInputNode上一篇心得记录中提到了 AudioGraph, 描述了一下 什么是 AudioGraph 以及其中涉及到的各种类型的 节点&#xff08;Node&#xff09;。 这一篇就其中比较有意思的 AudioFrameInputNode 来详细展开一…

Png透明背景的电话图标。

转载于:https://www.cnblogs.com/li0566/p/4343427.html

CSS改变nth-child()和nth-last-child()的参数灵活选择元素编号

注&#xff1a;下面的所有示例 1. div可以更换成任意标签 2. k是变量&#xff0c;可以换成特定数值&#xff0c;n保持不变 选中偶数行 div: nth-child(2n)div: nth-child(even) 选中奇数行 div :nth-child(odd)div :nth-child(2n-1) 选中前k行 div :nth-child(-nk) 选…

关于Silverlight中多项目共享DLL文件的讨论

假如你的解决方案中有两个Silverlight项目&#xff0c;其中的DLL文件时两个SL项目都使用到的&#xff0c;为了能够最大程度的减小XAP包的体积&#xff0c;你选择了系统的这个选项 编译后在Web的ClientBin文件夹下会出现这样的结构 这样呢&#xff0c;两个项目共享这些DLL的压缩…

核方法---径向基函数网络

为什么80%的码农都做不了架构师&#xff1f;>>> Nadarayas-Watson模型 转载于:https://my.oschina.net/liyangke/blog/2986510

c# 获取客户端IP地址方法

客户端ip: Request.ServerVariables.Get("Remote_Addr").ToString(); 客户端主机名: Request.ServerVariables.Get("Remote_Host").ToString(); 客户端浏览器IE&#xff1a; Request.Browser.Browser; 客户端浏览器 版本号&#xff1a; Request.Browser.M…

CSS结构选择器四种结构关系的范围

1. 空格&#xff1a; 表示<div>标签下所有的<h1>标签 div h1 2. >: 表示<div>标签下直接的<h1>标签 div>h1 3. ~:表示与<div>并列的所有<h1>标签 div~h1 4. :表示与<div>并列且紧邻的<h1>标签 divh1 注&#xff…

VMware前路难测,多个厂家群雄逐鹿

2019独角兽企业重金招聘Python工程师标准>>> 在人们高谈Salesforce、亚马逊等新兴云计算厂商取得的成就时&#xff0c;以VMware、HPE和Cisco为代表的老牌厂商也在进行着自己的转型和变化&#xff0c;而且还取得一定的进展。以VMware为例&#xff0c;虚拟机巨头公布了…