抽象工厂,是简单工厂的加强版,呵呵,比后者更加抽象化了,不过,的确很好用。
抽象工厂可以这么理解,你要到商场里去买衣服,好了,就这么多,就可以是抽象工厂模式,首先,你到商场里去买衣服,但是商场是抽象的,是不存在的,只是一个概念,那么,你要到哪个商场里去买衣服呢? 丹尼斯百货? 恩 这就是实实在在存在的商场了, 呵呵, 再者, 你要去买衣服,衣服也是抽象的,不存在的, 哦,我要去买CK内裤,哦 ,这就是实实在在的的衣服了,所以,这里可以理解为:
商场(抽象工厂)
丹尼斯百货(实体工厂)
衣服(抽象产品)
CK内裤(实体产品)
这里我们有一个需求,就是我要从数据库里分别读取学生和教师的姓名。就这么简单,但是,要求能在不同的数据库上移植。好了,我们现在分析,因为我们交给客户的都是直接编译好的class文件,所以,不要说去动源代码,其实我们可以用抽象工厂模式很好的解决这个问题,首先,我们看一个图
创建出抽象产品,就是规定你的实体产品必须实现什么功能,在这里我们只要求实体产品能够给我们提供返回学生或教师的姓名就就可以了
/*
* 定义接口IStudentService
*
* 规定所以实体产品必须能够返回学员姓名
*/
package MySchool.ISchoolService;
public interface IStudentService
{
String getStudentName();
}
/*
* 定义接口ITeacherService
*
* 规定所以实体产品必须能够返回教师姓名
*/
package MySchool.ISchoolService;
public interface ITeacherService
{
String getTeacherName();
}
我们创建出抽象工厂来,就是定义实体工厂都能生产出什么东西来,在这里只要能创建出学生和教师的数据库操作类就可以了
/*
* 抽象工厂类 AbsFactory
*
* 负责定义实体工厂所必须实现功能
*/
package MySchool.AbsFactory;
import MySchool.ISchoolService;
public abstract AbsFactory
{
abstract IStudentService getStudentService();
abstract ITeacherService getTeacherService();
}
这样我们就可以创建出实体产品了
//
// Mysql工厂能生产的两种产品
//
package MySchool.MySQLService;
import MySchool.ISchoolService;
public class StudentService implements IStudentService
{
public String getStudentName()
{
return "这里是从Mysql里读取到的学生姓名";
}
}
package MySchool.MySQLService;
import MySchool.ISchoolService;
public class TeacherService implements ITeacherService
{
public String getTeacherName()
{
return "这里是从Mysql里读取到的教师姓名";
}
}
//
// SQL Server工厂能生产的两种产品
//
package MySchool.SQLServerService;
import MySchool.ISchoolService;
public class StudentService implements IStudentService
{
public String getStudentName()
{
return "这里是从SQL Server里读取到的学生姓名";
}
}
package School.SQLServerService;
import MySchool.ISchoolService;
public class TeacherService implements ITeacherService
{
public String getTeacherName()
{
return "这里是从SQL Server里读取到的教师姓名";
}
}
接下来我们创建出各个实体工厂
//
// MySQL实体工厂,能够生产出学生和教师的操作类
//
package MySchool.MySQLFactory
import MySchool.ISchoolService;
import MySchool.AbsFactory;
import MySchool.MySQLService;
public class MySQLFactory extends AbsFactory
{
public IStudentService getStudentService()
{
return new StudentService();
}
public ITeacherService getTeacherService()
{
return new TeacherService();
}
}
//
// SQL Server实体工厂,能够生产出学生和教师的操作类
//
package MySchool.SQLServerFactory
import MySchool.ISchoolService;
import MySchool.AbsFactory;
import MySchool.SQLServerService;
public class SQLServerFactory extends AbsFactory
{
public IStudentService getStudentService()
{
return new StudentService();
}
public ITeacherService getTeacherService()
{
return new TeacherService();
}
}
既然我们能够在不改动代码的情况下移植数据库,那么我们就可以利用JAVA的反射技术来读取XML配置文件来动态改变访问具体数据库,我们来改写抽象工厂代码:
/*
* 抽象工厂类 AbsFactory
*
* 负责定义实体工厂所必须实现功能
*/
package MySchool.AbsFactory;
import MySchool.ISchoolService;
import MySchool.SQLServerFactory;
import MySchool.MySQLFactory;
public abstract AbsFactory
{
AbsFactory _factory=null;
public static absFactory getFactory()
{
//这里是读取XML和反射阶段,反射等以后再说,现在先假定是MySQL
//根据里氏替换原则
_factory=new MySQLFactory();
return _factory;
}
abstract IStudentService getStudentService();
abstract ITeacherService getTeacherService();
}
好了,现在我们再在业务逻辑层来调用查询学员或教师姓名的时候就可以这样来写,这里也用到了里氏替换原则
package MySchool.ShoolManager;
import MySchool.AbsFactory;
import MySchool.ISchoolService;
public class StudentManager
{
public String getStudentName()
{
IStudentService stuservice=AbsFactory.getFactory().getStudentService();
String name=stuservice.getStudentName();
return name;
}
}
这样 只需要配置XML就可以实现移植数据库功能了,当然,抽象工厂设计模式的应用绝非仅限于此,能不能把它玩转,就靠我们的造化了, 呵呵 还是 那样。 如果有错误的话还是请帮忙指出来, 其实模式是非常灵活的,没必要死板硬套,只要有那么点儿意思就可以了 O(∩_∩)O哈哈~
声明一点儿,代码是我用EditPus顺手捏来的,懒得动MyEclipse了,写出来只是作自己存起来日后看的,有个分号没加啊什么的就见谅了