本文共 11908 字,大约阅读时间需要 39 分钟。
提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体的类
对象:用户
数据库:数据库:两种方式 SQLserver以及 Access
用工厂方法模式的数据库访问程序
(1)Iuser接口
package com.factory;//IUSer接口,用于客户端访问,解除与具体数据库访问的耦合public interface Iuser { void Insert(User user); User GetUser(int id);}
(2)
package com.factory;//用于访问Sql Server的Userpublic class SqlserverUser implements Iuser{ @Override public void Insert(User user) { System.out.println("在Sql Server中给User表增加一条记录"); } @Override public User GetUser(int id) { System.out.println("在Sql Server中给根据ID得到User表的一条记录"); return null; }}
(3)
package com.factory;//用于访问Access的Userpublic class AccessUser implements Iuser{ @Override public void Insert(User user) { System.out.println("在Access中给User表增加一条记录"); } @Override public User GetUser(int id) { System.out.println("在Access中给根据ID得到User表的一条记录"); return null; }}
(4)
package com.factory;//定义一个创建访问User表对象的抽象的工厂接口public interface IFactory { Iuser CreateUser();}
(5)
package com.factory;//实例化SqlserverUserpublic class SqlServerFactory implements IFactory { @Override public Iuser CreateUser() { return new SqlserverUser(); }}
(6)
package com.factory;public class AccessFactory implements IFactory{ @Override public Iuser CreateUser() { return new AccessUser(); }}
(7)客户端代码
package com.factory;public class AccessFactory implements IFactory{ @Override public Iuser CreateUser() { return new AccessUser(); }}
(8)测试结果
在Sql Server中给User表增加一条记录在Sql Server中给根据ID得到User表的一条记录
对象: 用户,以及部门
数据库:两种方式 SQLserver以及 Access
和2.1相比,增加如下代码
(1) 部门类
package com.abstractfactory;public class Department { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
(2)Idepartment接口, 用于客户端访问,解除与具体数据库
package com.abstractfactory;public interface Idepartment { void Insert(Department department); Department GetUser(int id);}
(3)SqlServerDepartment类,用于Sqlserver操作department表
package com.abstractfactory;public class SqlserverDepartment implements Idepartment{ @Override public void Insert(Department department) { System.out.println("在SqlServer中向department表插一条记录"); } @Override public Department GetUser(int id) { System.out.println("在Sqlserver中给根据ID得到department表的一条记录"); return null; }}
(4)同理Accessdepartment
package com.abstractfactory;public class AccessDepartment implements Idepartment{ @Override public void Insert(Department department) { System.out.println("在ACcess中向department表插一条记录"); } @Override public Department GetUser(int id) { System.out.println("在Access中给根据ID得到department表的一条记录"); return null; }}
(5)修改Ifactory
package com.abstractfactory;//定义一个创建访问User表对象的抽象的工厂接口public interface IFactory { Iuser CreateUser(); Idepartment CreateDepartment();}
(6)修改SqlserverFactory
package com.abstractfactory;//实例化SqlserverUserpublic class SqlServerFactory implements IFactory { @Override public Iuser CreateUser() { return new SqlserverUser(); } @Override public Idepartment CreateDepartment() { return new SqlserverDepartment(); }}
(7)修改AccessFactory
package com.abstractfactory;public class AccessFactory implements IFactory { @Override public Iuser CreateUser() { return new AccessUser(); } @Override public Idepartment CreateDepartment() { return new AccessDepartment(); }}
(8)客户端
package com.abstractfactory;public class Client { public static void main(String[] args) { User user =new User(); Department department=new Department(); IFactory factory=new AccessFactory();//若要改变为Access数据库,只需将本句改为 // IFactory factory=new SqlServerFactory(); Iuser iuser=factory.CreateUser(); //与具体数据库访问解除了依赖 Idepartment idepartment=factory.CreateDepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}
(9)测试结果
在Access中给User表增加一条记录在Access中给根据ID得到User表的一条记录在ACcess中向department表插一条记录在Access中给根据ID得到department表的一条记录
Ifactory中包含所有产品创建的抽象方法。
为创建不同的产品对象,客户端使用不同的具体工厂。
优点
缺点
增加实体类的时候要改动很多地方,比如增加company表,就需要增加ICompany接口,SqlserverFactory,AccessFactory,还需要改动Ifactory, SqlserverCompany以及AccessFactory
设计Dataaccess类,
package com.simpleFactory;public class DataAccess { private static String db="SqlServer"; //在这里该数据库类型 //private static String db="Access"; public static Iuser CreateUser(){ Iuser result=null; switch (db){ //前边已经选好了数据库 case "Sqlserver": result=new SqlserverUser(); break; case "Access": result=new AccessUser(); break; } return result; } public static Idepartment CreateIdepartement(){ Idepartment result=null; switch (db){ case "Sqlserver": result=new SqlserverDepartment(); break; case "Access": result=new AccessDepartment(); break; } return result; }}
更改客户端
package com.simpleFactory;public class Client { public static void main(String[] args) { User user =new User(); Department department=new Department(); //因为事先选好了用的数据库,所以可以直接得到数据库访问实例,客户不需要了解是用的什么数据库 Iuser iuser=DataAccess.CreateUser(); //因为设置的都是静态函数,直接用 Idepartment idepartment= (Idepartment) DataAccess.CreateIdepartement(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}
简单工厂方法的确实现了客户端不需要知道Sqlser和ACcess数据库, 但是如果再加一个数据库比如oracle,就不是抽象工厂方法中增加oracleFactory那么简单了,需要再DataAccess的每个函数中的switch中加Case
JAVA反射机制是就是运行的状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。通过反射机制可以动态的访问类的属性和方法以及字段。
最常用的反射机制就是:
(类)Class.forName("obj name").newInstance();
package com.reflection;public class DataAccess { private static String AssemblyName="com.reflection"; //根目录Src下的路径 private static String db="Sqlserver"; //可以替换成任意类型的数据库,比如access public static Iuser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException { String classname=AssemblyName+"."+db+"User"; return (Iuser)Class.forName(classname).newInstance(); //根据字符串 "com.reflection.SqlserverUser"匹配com.reflection.SqlserverUser类 } public static Idepartment CreateIdepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException { String classname=AssemblyName+"."+db+"Department"; return (Idepartment) Class.forName(classname).newInstance(); }}
成功的前提是com.reflection.SqlserverUser,SqlserverDepartment这些类存在
客户端没有变化
package com.reflection;public class Client { public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { User user =new User(); Department department=new Department(); Iuser iuser= DataAccess.CreateUser(); Idepartment idepartment= DataAccess.CreateIdepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}
执行结果
在Sql Server中给User表增加一条记录在Sql Server中给根据ID得到User表的一条记录在SqlServer中向department表插一条记录在Sqlserver中给根据ID得到department表的一条记录
完整代码:
(1)实体类
package com.reflection;public class User { private int _id; private String _name; public int get_id() { return _id; } public void set_id(int _id) { this._id = _id; } public String get_name() { return _name; } public void set_name(String _name) { this._name = _name; }}
package com.reflection;public class Department { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
(2) 实体表接口,事先客户端与实体表的解耦
package com.reflection;//IUSer接口,用于客户端访问,解除与具体数据库访问的耦合public interface Iuser { void Insert(User user); User GetUser(int id);}
package com.reflection;public interface Idepartment { void Insert(Department department); Department GetUser(int id);}
(3) 具体数据库操作每个实体
Access数据库
package com.reflection;//用于访问Access的Userpublic class AccessUser implements Iuser { @Override public void Insert(User user) { System.out.println("在Access中给User表增加一条记录"); } @Override public User GetUser(int id) { System.out.println("在Access中给根据ID得到User表的一条记录"); return null; }}
package com.reflection;public class AccessDepartment implements Idepartment { @Override public void Insert(Department department) { System.out.println("在ACcess中向department表插一条记录"); } @Override public Department GetUser(int id) { System.out.println("在Access中给根据ID得到department表的一条记录"); return null; }}
Sql server数据库
package com.reflection;//用于访问Sql Server的Userpublic class SqlserverUser implements Iuser { @Override public void Insert(User user) { System.out.println("在Sql Server中给User表增加一条记录"); } @Override public User GetUser(int id) { System.out.println("在Sql Server中给根据ID得到User表的一条记录"); return null; }}
package com.reflection;public class SqlserverDepartment implements Idepartment { @Override public void Insert(Department department) { System.out.println("在SqlServer中向department表插一条记录"); } @Override public Department GetUser(int id) { System.out.println("在Sqlserver中给根据ID得到department表的一条记录"); return null; }}
(4) 数据库抽象工厂, 利用配置文件+反射
使用反射替代了简单工厂的switch
用户改数据库类型,只需在配置文件中改!
db=Access
package com.reflection;import java.util.ResourceBundle;public class DataAccess { private static String AssemblyName="com.reflection"; //读取配置文件中的db类型 ResourceBundle resource1=ResourceBundle.getBundle("com/reflection/App"); //通过用户输入的来取指定类 private String db=resource1.getString("db"); //可以替换成任意类型的数据库,比如access public Iuser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException { String classname=AssemblyName+"."+db+"User"; return (Iuser)Class.forName(classname).newInstance(); } public Idepartment CreateIdepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException { String classname=AssemblyName+"."+db+"Department"; return (Idepartment) Class.forName(classname).newInstance(); }}
(5)客户端
package com.reflection;public class Client { public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException { User user =new User(); Department department=new Department(); DataAccess dataAccess=new DataAccess(); Iuser iuser= dataAccess.CreateUser(); Idepartment idepartment= dataAccess.CreateIdepartment(); iuser.Insert(user); iuser.GetUser(1); idepartment.Insert(department); idepartment.GetUser(1); }}
运行结果
在Access中给User表增加一条记录在Access中给根据ID得到User表的一条记录在ACcess中向department表插一条记录在Access中给根据ID得到department表的一条记录
转载地址:http://dvfdi.baihongyu.com/