论坛首页 Java企业应用论坛

从Spring MVC扩展中学习OO设计(一)

浏览 5920 次
精华帖 (0) :: 良好帖 (13) :: 新手帖 (0) :: 隐藏帖 (5)
作者 正文
   发表时间:2010-02-12   最后修改:2010-02-12
OO

对于刚刚接触Java的人来讲经常的一个疑问就是“接口与抽象类有何不同?”,为了回答这个问题,我们可以从一个扩展Spring Controller的例子来看看接口与抽象类的不同及如何将其使用在OO设计中。

 

需求的场景是这样的:扩展Controller实现返回Json数据格式的Ajax的Controller,对于继承后的子类只需实现返回要序列化为Json数据格式的对象,而无需关注如何返回Json数据。

 

实现了需求场景的实例:

 

基本接口定义,定义返回Json数据格式的方法。扩展的抽象类需实现此方法。

public interface JsonProvider {
	
    abstract void pushJsonResponse(HttpServletResponse response, Object obj) throws IOException;

}

 

实现了接口的抽象类,此类实现了接口中定义的pushJsonResponse()方法,并加入了新定义的抽象方法handleJsonRequest(),供子类实现

/**
 * Description:<br>
 * Origin Time: 2009-6-12 上午11:07:18<br>
 * 
 * @author Seraph<br>
 * @email:seraph115@gmail.com<br>
 */
public abstract class JsonProviderController extends AbstractController
		implements JsonProvider {

	private static final Log log = LogFactory
			.getLog(JsonProviderController.class);

	public void pushJsonResponse(HttpServletResponse response, Object obj)
			throws IOException {

		if (obj == null) {
			obj = new Object();
			log.warn("obj is null");
		}

		ResponseUtils.setJsonHeader(response);
		PrintWriter out = response.getWriter();

		out.print(JsonUtils.toJson(obj));
		out.close();
	}

	protected abstract Object handleJsonRequest(HttpServletRequest request,
			HttpServletResponse response);

	@Override
	protected ModelAndView handleRequestInternal(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		Object obj = handleJsonRequest(request, response);
		pushJsonResponse(response, obj);
		return null;
	}

}

 

继承后的子类,享用了抽象类实现的接口方法,自己只需要实现抽象类中的抽象方法,返回要Json序列化的对象即可

/**
 * 类说明:<br>
 * 创建时间: 2008-8-15 上午11:07:55<br>
 * 
 * @author Seraph<br>
 * @email: seraph115@gmail.com<br>
 */
public class AsyncMenuProviderController extends JsonProviderController {

	private TreeManager treeManager;

	public void setTreeManager(TreeManager treeManager) {
		this.treeManager = treeManager;
	}

	@Override
	protected Object handleJsonRequest(HttpServletRequest request,
			HttpServletResponse response) {

		String rootId = request.getParameter("id");

		List<AsyncTreeNode> result = new ArrayList<AsyncTreeNode>();
		List<AsyncTreeNode> list = treeManager.getLowerTreeNodeByRole(rootId);

		if (null != list) {
			result = list;
		}

		return result;
	}

}

 

此例同时使用了接口和抽象类,完成了扩展自SpringController得JsonProviderController,便于让继承后的子类完成返回Json数据格式的能力。其中在抽象类中实现了繁琐的返回Json数据格式的方法,让后续的子类大大简化了代码,甚至感觉不到与普通的Controller有何不同。

 

接口定义了统一的行为,对于此行为可以有多种实现,而实现接口的抽象类完成了绝大部分的工作,把脏活和累活都一个人承担了下来,留给子类一个需实现的抽象方法来调用。

 

 

让我们回过头来看看刚才的问题,即“接口与抽象类的不同”:

 

从此例中我们可以看出接口完成的是定义统一的行为,同时也是对所实现类的一种归类和约束,告诉了我们实现此接口的类都具有相同的特性,应归为一类,在很多应用设计中我们使用空定义的接口来划分类的规属及关系,接口补充了Java的多继承能力而又不会导致象C++中由多继承引发的程序复杂化问题;

 

而抽象类即可以实现方法又可以定义抽象方法,抽象类可以替子类实现部分功能,把其中变化的部分交给子类来完成,具体是可以把子类共有的代码放入抽象类中完成,此复用可以大大简化代码量及其利用率。

 

所以接口就像是本儿武当派的秘籍,是种规范,规定你如何去打,如何运用此门武功。而抽象类更像是你武当派的师傅,他教你怎样打,并告诉徒弟们应该有创新,应该有自己的招式,这样在他的指导下你就进步了,学会了本来不会的武功,并专注于研究你自己的招式。

 

对于OO设计中如何使用接口及方法的深刻理解还需我们在实际使用中体会其美妙之处,好的设计使代码简洁易懂,易于维护和扩展,在日积月累也不会变的腐臭不堪,会长久的保持其简单的复杂度。基本的设计原则就是类的单一职能,允许扩展但不容更改。所以很多经验是积累的结果,要善于总结和钻研,所以有时偏执的完美主义者才能成功。作为软件开发者完美主义能让你成长的更快。

 

   发表时间:2010-02-18  
说的非常好..顶下
0 请登录后投票
   发表时间:2010-02-19  
读了之后,受益匪浅。做一个会思考的人
0 请登录后投票
   发表时间:2010-02-20  
惭愧,只会用SpringMVC,却从没想过去思考它!!
0 请登录后投票
   发表时间:2010-02-21  
很好的。 正在学习Spring MVC
0 请登录后投票
   发表时间:2010-02-21  
楼主一言,甚造七级浮屠啊,SpringMVC以前用过。
0 请登录后投票
   发表时间:2010-02-21   最后修改:2010-02-21
个人认为JsonProvider这个接口没有存在的必要,这个例子里只用抽象类已经可以约束子类的行为。
至少从命名和实际需求上来来看JsonProviderController对JsonProvider的实现已经很唯一了,出现其他实现类的预期和意义都不大。而且接口里的方法没必要声明abstract吧
0 请登录后投票
   发表时间:2010-02-22  
这是模板设计模式的一种应用。
0 请登录后投票
   发表时间:2010-02-22  
模板模式的应用实践,很不错啊,这个为啥投隐藏啊??不解!!
应该是个很好的教学用例啊。UP一下
0 请登录后投票
   发表时间:2010-02-22   最后修改:2010-02-22
fangin 写道
个人认为JsonProvider这个接口没有存在的必要,这个例子里只用抽象类已经可以约束子类的行为。
至少从命名和实际需求上来来看JsonProviderController对JsonProvider的实现已经很唯一了,出现其他实现类的预期和意义都不大。而且接口里的方法没必要声明abstract吧


首先谢谢你的回复,对于你对JsonProvider这个接口设计的疑问,其意义在于定义了一种规范,居于设计中继承树的顶端,因为除此JsonProviderController的抽象实现外还有其他同级的抽象实现,这个我会在接下来的blog中列举,而抽象类完成了公共行为的封装,是公共的父类为子类的扩展(使用)提供基础。

对于接口里的abstract方法是的确是种习惯,因不声明abstract,接口中的方法也同样是抽象的。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics