`
whao189
  • 浏览: 124653 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

侃侃重构(refactor)一

 
阅读更多
话说距离上次发文章已经是时隔将近一个半月了,期间忙着项目所以对于文章或者说知识的总结就给忽略了!

这次我们来说说重构,说之前要感谢带领我入门的那些大哥(我曾经的同事,我喊他锋哥,还有经理 包大哥),那个时候虽然大家都在讨论但是我作为一个菜鸟级的人物,听得不太懂不过现在做android 这一块我发现代码真是乱,所以就想到了这个东西,于是乎就做了一把refactor!

个人理解重构的概念
重构:就是在不改变现有软件的质量以及运行的情况下,对代码的整理以及对逻辑的从新梳理,已达到逻辑清晰,代码可读性好,整洁这样一个效果!
以上是我个人的理解,有误之处请大家指出来啊!无喷!

那么好了接下来说例子,因为我做的android 项目现在负责的就是xml解析数据 以及返回给 activity 数据 先来了解一下结构类图如下:

这是 原来没有重构之前的类图,需要说明的是service 和handler的子类有很多个!

下面说一下service 和 handler 里面的方法。。。

在每个service 和 handler 里面都包含有这样一个方法getXXXtBean():Object 返回的都是 具体的类型。。。(我这到这样做不好)

下面我们重点说一下 service 里面的方法。。

代码如下:
public static CheckOutBean getCheckOutBean(Context context,String playlistId,String pID) throws ParserConfigurationException, SAXException, IOException{
		String urlPath = URLRequest.CHECKOUT.getUrl()+"playlistid="+ playlistId + "&pid="+ pID;         //这个地方每个sevice 的url 不同
		InputStream inputStream = HttpClient.getInputByHttpConn(urlPath,context);
		if(null != inputStream){
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser        parser  = factory.newSAXParser();
			ParserCheckOutXMLHandler handler = new ParserCheckOutXMLHandler();//这个地方调用的 handler 不同
			parser.parse(inputStream, handler);
			return handler.getCheckOutBean();  //返回的对象不同
		}
			return null;
	}



public static CheckUserPlayingBean getCheckUserPlayingBean(Context context,String playlistId) throws ParserConfigurationException, SAXException, IOException{
		
		String url = URLRequest.CHECKUSERPLAYING.getUrl()+ playlistId;
		InputStream inputStream = HttpClient.getInputByHttpConn(url,context);
		if(null != inputStream){
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser      saxParser = factory.newSAXParser();
			ParserCheckUserPlayingXMLHandler handler = new ParserCheckUserPlayingXMLHandler();
			saxParser.parse(inputStream, handler);
			
			return handler.getCheckUserPlayingBean();
		}
			return null;
	}

注意比较上面两段代码,他们是否存在共同之处呢?

/*********以上是重构之前的代码和结构*********************************************/

现在总结一下:我们从上面的图 和 代码中应该能察觉到这写个handler 子类 以及 service 类中存在相同的代码! 而且他们在service处理 拿到对象的逻辑是相同的。。。


所以我在做完这一期项目之后就考虑了一下进行重构一把(不过千万别忘了单元测试。。。如果重构之后没有做测试,那么我觉得你的工作只能说做了40%)!

那好接下来说说我重构的思路。。。。

因为service中存在项目的方法 和逻辑我想了一下就是准备使用模板方法 模式来进行重构!

他们出来对象的逻辑是相同的。因此我就有了这样个 BaseService

代码:

public abstract class BaseService {
	int retryTimes = 5;
	protected Context context;
	protected String url;
	protected InputStream inputStream;
	protected SAXParserFactory factory;
	protected SAXParser parser;
	protected MyDefaultHandler handler;
	protected Object object;

	protected final void template(){
		getInputStream();
		if( null != inputStream ){
			factory = SAXParserFactory.newInstance();
			try {
				parser  = factory.newSAXParser();
				handler = getHandler();
				parser.parse(inputStream, handler);
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			this.object = handler.getBean();
		}
	}
	private void getInputStream(){
//这个方法 是因为某些 service 处理的逻辑需要反复的 去判断网络是否正常
//所以我使用了一个callBack方法。。让子类决定是否调用这里面的逻辑
		if(callBack()){
			while(retryTimes>=1){
				inputStream = HttpClient.getInputByHttpConn(loadUrl(), context);
				if(null != inputStream){
					break;
				}
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				retryTimes --;
			}
		}
		inputStream = HttpClient.getInputByHttpConn(loadUrl(), context);
	}
	protected abstract String loadUrl();
	protected abstract MyDefaultHandler getHandler();
	
	protected boolean  callBack(){
		return false;
	}
}



没有baseservice之前我们的处理方式就如同上面的那种。。。(getCheckOutBean() getCheckUserPlayingBean()) 但是他们的程序逻辑是一样的。

都是先拿到url  然后 交给httpclient类产生inputstream 之后就是判断是否为空,接着就是
产生handler 让后让handler解析,最后就是拿到 handler 处理之后的对象!


现在我们看看baseservice 的tempalte 方法。。final 的防止子类修改 整个处理逻辑!
是的吧,是和原来一样的逻辑!没错,你是对的,就是这样的。。。然后让所有的service子类都去继承 这个baseservice 。。。。

注意你看到了。。在baseservice中包含了。。MyDefaultHandler对象。。。。这里之所以这么做,是因为。。每一个 handler 之类在解析完之后都会产生具体的 对象。。

如果是 PlayingListBeanHandler 就产生。。。PlayingListBean对象。。。如果是

CheckOutBeanHandler 就产生。。CheckOutBean ..。。看原来的类图中。。可以看到这些方法。。的。。。

所以我就想这些对象都是 Object的子类。。为何不能定义一个通用的方法。。返回Object 然后具体的类型都交给 调用类来转换。。。

this.object = handler.getBean(); //就是这一句了。。呵呵。。

来看看。。MyDefaultHandler 。。
public abstract class MyDefaultHandler extends DefaultHandler {

	public abstract Object getBean();
}


只有这样一个方法。。。。abstract 来修饰的。。呵呵!!!

看重构之后的类图:



接下来看重构之后的service代码:

private String  playlistId;
	private String  pID;
	
	public ParserCheckOutService(){}
	
	public ParserCheckOutService( 
			Context context,String playlistId,String pID){
		this.context = context;
		this.playlistId = playlistId;
		this.pID = pID;
		
		this.template();//这个地方要注意了。。。。记得调用啊。。
	}
	@Override
	protected String loadUrl() {
		return URLRequest.CHECKOUT.getUrl()+"playlistid="+ playlistId + "&pid="+ pID;
	}

	@Override
	protected MyDefaultHandler getHandler() {
		return new ParserCheckOutXMLHandler();
	}
	public CheckOutBean getCheckOutBean() {
		return (CheckOutBean)object;
	}



好了。。看看是不是比之前的代码 清晰了。。。要是再有需求来了。。我就写一个service 继承。。basservice 。。。然后程序逻辑不需要改变。。。也没必要知道 是怎么写的。。
直接实现方法。。就可以了。。呵呵。。。应该说达到了。。代码的复用!

对了。。我们来看一下钩子函数的 。。调用代码

当你需要调用。。如下代码的时候。。

if(callBack()){
	while(retryTimes>=1){
			inputStream = HttpClient.getInputByHttpConn(loadUrl(), context);
				if(null != inputStream){
					break;
				}
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				retryTimes --;
			}
		}


你只需要让 baseservice 重写这个。。callback方法即可。。
@Override
	protected boolean callBack() {
		return true;
	}


、。。。这样是不是感觉。。代码清晰很多了呢!!!  这里我要感谢一下现在的同事,我最初重构的效果并非如此,要感谢他的建议!!!呵呵。。。



  • 大小: 70.4 KB
  • 大小: 105.8 KB
  • 大小: 104.1 KB
分享到:
评论

相关推荐

    refactor(重构-改善既有代码的设计)

    refactor(重构-改善既有代码的设计),中文版共15章

    详解AndroidStudio中代码重构菜单Refactor功能

    Android Studio中代码重构菜单Refactor功能是一个功能强大且实用的工具,旨在帮助开发者提高代码质量和开发效率。在Android Studio的主菜单栏中有一项“Refactor”下拉菜单,点击该下拉菜单,会显示出多种代码重构...

    代码的重构,改善代码设计 refactor

    代码重构是软件开发中的一项持续性工作,目的是改善现有代码的质量而不改变其外部行为。重构的重要性不言而喻,它能帮助我们增强代码的可维护性、可读性和可扩展性。在本篇中,我们将详细介绍重构的定义、方法、原则...

    Delphi XE Refactor重构功能简单说明 .mht

    Delphi XE Refactor重构功能简单说明 .mht

    js2-refactor.el, emacs的JavaScript重构库.zip

    js2-refactor.el, emacs的JavaScript重构库 js2-refactor.el emacs的JavaScript重构库。这是一个小型重构函数的Collection,以进一步了解从js2-mode开始的Emacs中的JavaScript IDE 。在 0.8.0中更改添加 e

    Refactor pro

    1. **智能重构**:Refactor Pro提供了一系列智能重构操作,包括提取方法、提取变量、内联变量、重命名、移动和复制代码块等,这些功能能够帮助开发者快速调整代码结构,提高代码可读性和可维护性。 2. **代码分析**...

    sublime-text-refactor, 用于Javascript代码的sublime text 重构插件.zip

    sublime-text-refactor, 用于Javascript代码的sublime text 重构插件 用于 sublime-text-2和 3的 Javascript重构插件 [[Package Control] ( https://packagecontrol.herokuapp.com/downloads/JavaScript%2

    BuildSql Refactor

    【标题】"BuildSql Refactor" 是一个关于SQL构建和重构的工具或技术,它旨在提高数据库查询代码的效率和可维护性。SQL重构通常涉及优化查询语句、规范化数据库结构以及改善数据访问模式,以提升应用性能。在这个场景...

    vim-refactor:Vim的通用重构插件

    对于Vim用户来说,`vim-refactor`是一个非常实用的插件,它提供了丰富的重构功能,帮助开发者在Vim编辑器中高效地进行代码重构工作。 1. **什么是vim-refactor** `vim-refactor`是一个专门针对Vim设计的重构工具集...

    Python代码重构的艺术:探索自动化重构工具

    1. **Rope**:一个专为Python设计的重构库,支持诸如重命名、提取方法、移动代码等常见重构操作。Rope可以集成到各种IDE和编辑器中,如PyCharm、Vim等,极大地提高了重构的灵活性。 2. **PyCharm**:作为一款流行的...

    refactor(FrameWork4.0)

    标题"refactor(FrameWork4.0)"暗示了这次我们将讨论的是一个针对Framework 4.0的重构过程。 重构是对现有代码进行修改,以改善其内部结构,而不改变其外部行为的过程。在.NET Framework 4.0的背景下,重构可能是...

    软件重构技术的本质

    重构(Refactor,动词)则是指执行一系列这样的操作,以逐步改善代码质量。这种改变的核心在于保持原有的功能不变,同时提升代码的结构和设计。 2. 重构的原则: - 单一职责:在开发过程中,应明确区分添加功能和...

    emacs-refactor:Emacs中特定于语言的重构

    "emacs-refactor"是Emacs生态系统中的一个工具,它为Emacs提供特定于语言的代码重构支持,使开发人员能够在Emacs环境中进行高效的代码改进和优化。在本文中,我们将深入探讨emacs-refactor及其对Emacs用户的意义,...

    代码重构源码(包含重构前后代码)

    代码重构是一种重要的软件开发实践,旨在改进代码的结构和可读性,而不改变其外部行为。这个压缩包文件“代码重构源码(包含重构前后代码)”提供了面向对象编程领域中的一个实例,具体是对影片出租店租赁程序的重构...

    DeveExpress Refactor!Pro 3.0.5

    Pro是一款专为Visual Studio设计的高效代码重构工具,其3.0.5版本在2008年1月15日进行了官方更新。这个强大的插件致力于帮助开发者提升编程效率,优化代码质量,通过智能重构功能让代码更加清晰、易于维护。 1. **...

    How we refactor, and how we know it

    1. **重构记录的缺失**:研究发现,程序员在进行重构时,很少会在版本控制系统的提交日志中明确标注其活动为重构。这与之前许多研究者所持有的观点相悖,他们通常假设重构活动会被明确记录在提交日志中。这一发现...

    Refactor!Pro 3.0.5

    Pro 3.0.5是一款专为Visual Studio 2005和2008设计的高效代码重构工具,它极大地提升了开发人员在.NET框架下的编程效率。这款软件以其强大的功能和对开发者友好性的设计,被誉为CodeRush系列的重要组成部分,旨在...

    Refactoring To Patterns《重构与模式》英文版

    《重构与模式》是一本由Joshua Kerievsky编写的书籍,由Addison Wesley出版社于2004年8月5日出版,ISBN号为0-321-21335-1,全书共400页。该书旨在将重构技术和设计模式有效地结合起来,通过一系列具体的案例分析和...

    重构那点事情

    - **IDE Refactor 功能**:大多数现代集成开发环境 (IDE) 都提供了重构功能,如物理重组与重命名 (Rename、Move),重新定义类之间的关系,转换匿名类 (Convert Anonymous Class),以及在类继承关系内移动成员 (Push ...

Global site tag (gtag.js) - Google Analytics