您的位置:首页 > 编程语言

如何写出漂亮的代码——巧妙的接口扩展

2013-05-09 23:00 609 查看
最近对面向对象有了个新的领悟,特在此分享给大家。如果这个思想不对或者已经out了,还请不要笑话。

本文的示例代码将以ASP.NET MVC为基础的,如果你没有MVC的基础,也不会影响阅读,因为本文探讨的核心是面向对象中的一个设计思想。

下面我先以一个简单的例子来描述它。

案例:

有时我们的一个项目包含多个网站,比如有一个管理员用的站点,有一个公司客户使用的站点,这2个站点会部署到不同的服务器。这2个站点都有一个注销登录的action。你可能首先想到,用一个UserControllerBase类来封装这个logout action,以实现代码的重用。这当然是我们首先考虑到的。但是,有时候这2个站点的controllers分别继承了不同的controllerBase,比如AdminControllerBase和ClientControllerBase,这时再用类的继承来实现就不太优雅了。

解决方案:

定义一个ILogoutController接口,然后对该接口写扩展方法Logout,然后再让不同站点的UserController实现这个接口。

代码:接口定义和扩展实现

namespace Demo
{
public interface ILogoutController
{

}

public static class LogoutControllerExtensions
{
public static ActionResult Logout<TController>(this TController controller)
where TController : DemoControllerBase, ILogoutController
{
var service = IoC.GetService<IUserService>();
service.Signout(controller.User.Identity.Name);
controller.Session.Clear();
controller.Session.Abandon();
FormsAuthentication.SignOut();
return controller.DemoRedirect("/login");
}
}
}


代码:让相应的controller实现该接口

namespace Demo.Admins
{
public class UserController : AdminControllerBase, ILogoutController
{
public ActionResult Logoff()
{
return this.Logout();
}
}
}

namespace Demo.Clients
{
public class UserController : ClientControllerBase, ILogoutController
{
public ActionResult Logoff()
{
return this.Logout();
}
}
}


上面代码的核心在于接口扩展方法的泛型约束 where TController : DemoControllerBase, ILogoutController。另外还请注意到扩展方法的最后一行代码:

return controller.DemoRedirect("/login");


由于System.Web.Mvc.Controller的Redirect方法是protected,为了让该方法公开出来,在这个例子中我们新加了一个DemoControllerBase,如下:

public class DemoControllerBase : Controller
{
public RedirectResult DemoRedirect(string url)
{
return base.Redirect(url);
}
}

public class AdminControllerBase : DemoControllerBase
{

}

public class ClientControllerBase : DemoControllerBase
{

}


其他适用场景:

可以说这一设计思想可以应用到任何场景,可以说这一思想即是面向对象编程思想的一部分。你可以发现,上面的代码是完全符合面向对象思想的。代码非常容易阅读,可维护性高,可扩展性强。

在我们的项目中,除了上面的ILogoutController外,还有一个IAddressEditorController。由于我们的项目分为4个站点,有很多的用户角色,地址编辑出现在很多地方。自从有了这个接口之后,代码就漂亮多了,如果客户想要增加一个地址编辑页面,对我们的成本的增加那就几乎是0.

“接口扩展”这一思想不仅仅是可以应用于web层的controller,其实可以应用于任何地方。

思想的升华:

本人觉得使用“接口扩展”的设计要比用基类的设计要好些,因为“接口扩展”像是一种注入式的代码,我们可以将接口封装的特性注入到任何一个类上面,而不用去处理复杂的类的继承。

给你的实体类注入新特性吧!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: