面向对象之抽象方法实践
面向对象的重要概念就是抽象。抽象的目的是为了应对变化。这个抽象一词本身太抽象,所以以致我们在实践面向对象分析、设计以及开发的使用,不知道怎么抽象。不能很好把握抽象的概念,就不能很好理解面向对象。
抽象是面向对象的精髓。
事实上很多时候我们使用的框架中的许多类都是抽象的,比如DbCommand, MembershipProvider
例子:使用平台抽象类应对变化
现在使用例子来演示抽象,程序中的一个对象ProductDAL使用数据库访问技术访问数据库并返回Product数据。
public class ProductDAL
{
public Product GetProduct(string productId)
{
// 使用ADO.net 数据访问SQL Server database
// setup connection
// create command and execute command
// return result
}
}
ProductDAL对象编程实现本身没有问题,程序运行起来也没有问题。
世界是时刻在变化的,需求也在变。
客户说我的数据库不是SQL Server,我的数据库是Oracle的。程序员回答,那我改改程序,把ProductDAL代码中的Ado.net 类使用抽象的DbCommand,在运行的时候由容器注入DbCommand的实例。ProductDAL使用的数据访问技术是Ado.net,这种技术能支持Oracle和Sql Server,甚至你是MySql的也没有问题. 只要你改改程序的配置文件就可以运行了.客户问怎么能不这次不用改程序啦?是的,只改一下配置程序就能访问Oracle数据库,答案就是我们使用的是抽象的DbConnection和DbCommand,而不是具体的SQLCommand,所以能应对这种需求的变化。
上面我们讲的是Net平台的抽象对象能有效应对变化,那么自己在设计对象的时候应该怎么抽象呢?
怎么使用面向对象的抽象方法来设计对象
现在客户说我们现在不使用Oracle数据库了,我们使用外部的Web Service,这个时候程序员这个时候就需要再改了,怎么改呢?
改成下面的怎么样?
public class ProductDAL
{
public Product GetProduct(string productId)
{
// if use database as data storage {
// 使用ADO.net 数据访问SQL Server database
// setup connection
// create command and execute command
// return result
// if use web server as data source {
// web service invoke method
// return result
}
}
}
}
上面的方法明显违反了面向对象原则之一对修改封闭,对扩展开发(OCP原则)
抽象就是做什么与如何做分离
ProductDAL不能有效应对使用WebService作为外部数据源主要是因为,ProductDAL把所有的任务一个人干了。
那么既然在ProductDAL里面改不能应对这种需求的变化,我们就往上一个层次来考虑,那上一个层次是什么呢(我这里不是指三层应用程序架构模式)。这两个层次是“做什么”与“如何做”
很多情况都是需要使用两个层次来隔离变化,降低复杂度。也就是说ProductDAL是“如何做”层次,因为它把如何访问数据库的细节都考虑了。
那么“做什么”层次是什么对象呢,很简单可以使用编程语言的接口或抽象对象类,这个“做什么”对象之关心与外部的接口,外部需要我做什么,自己不实现。
具体方法就是抽象一个接口类IProductDAL或者抽象对象AbstractProductDAL就能解决实际情况使用不同数据源的问题。 ProductDAL实现IProductDAL的方法,而WebService或文件型的数据源,也可以实现这个接口。 这样就做到了两个层次一个层次(IProductDAL)关注做什么,一个层次(ProductDAL)关注怎么做。外部使用IProductDAL就可以了。至于具体使用什么数据源留给客户去配置。
上面的两个例子演示了使用平台抽象类应对变化以及怎么使用面向对象的抽象方法来设计对象以达到应对变化的目的。