package abstracFactoryModel;
/**
*这里是连接数据库的一个例子 就不写一遍的连接了 直接用工厂方法模式来实现
*/
public class Commonly {
public static void main(String[] args) {
User user = new User();
Ifactory ifactory = new MysqlFctory();//如果换成了Oracle 数据库 那么把这里换成OracleFctory就行了
IUser iUser = ifactory.CreateUser();
//插入User 获取User
iUser.Insert(user);
iUser.GetUser(2);
//一个系统不可能只有一个User表 如果加一个其他表呢 比如部门表需要增加代码 看Commonly2
Depaertment depaertment = new Depaertment();
IDepaertment iDepaertment = ifactory.CreateDepartment();
//插入Department 根据id获取Department
iDepaertment.Insert(depaertment);
iDepaertment.GetDepaertment(1);
//!!!! 只有一个user类和user操作的时候 是只需要工厂方法模式的
//但现在显然数据库中有很多表 而且MySQL 和 oracle 有事2个不同的分类 所以解决这种
//涉及到多个产品系列的问题 有一个专门的工厂模式--》抽象工厂模式
}
}
/*
* 用户类
*/
class User{
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;
}
}
/*
* User操作抽象类
*/
interface IUser{
void Insert(User user);
User GetUser(int i);
}
/*
* 具体实现(Mysql)
*/
class MysqlUser implements IUser{
public void Insert(User user) {
System.out.println("在mysql中插入用户数据");
}
public User GetUser(int i) {
System.out.println("根据id从mysql中获取数据");
return null;
}
}
/*
* 具体实现(Oracle)
*/
class OracleUser implements IUser{
public void Insert(User user) {
System.out.println("在Oracle中插入用户数据");
}
public User GetUser(int i) {
System.out.println("根据id从Oracle中获取数据");
return null;
}
}
// 通过工厂获取具体对象 这就是工厂方法
/*
*抽象工厂
*/
interface Ifactory{
IUser CreateUser();
// 新增++++ 获取department
IDepaertment CreateDepartment();
}
/*
* mysql工厂
*/
class MysqlFctory implements Ifactory{
public IUser CreateUser() {
return new MysqlUser();
}
// 新增++++ 获取department
public IDepaertment CreateDepartment() {
return new MysqlDepaertment();
}
}
/*
* Oracle工厂
*/
class OracleFctory implements Ifactory{
public IUser CreateUser() {
return new OracleUser();
}
// 新增++++ 获取department
public IDepaertment CreateDepartment() {
return new OracleDepaertment();
}
}
package abstracFactoryModel;
/**
*这里是连接数据库的一个例子 就不写一遍的连接了 直接用工厂方法模式来实现
*/
public class Commonly2 {
public static void main(String[] args) {
User user = new User();
Ifactory ifactory = new MysqlFctory();//如果换成了Oracle 数据库 那么把这里换成OracleFctory就行了
IUser iUser = ifactory.CreateUser();
//插入User 获取User
iUser.Insert(user);
iUser.GetUser(2);
}
}
/*
* 如果增加一个部门 需要增加如下代码
*/
/*
* 这个类是必不可少的
*/
class Depaertment{
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;
}
}
/*
* 抽象
*/
interface IDepaertment{
void Insert(Depaertment depaertment);
Depaertment GetDepaertment(int id);
}
/*
* Mysql实现
*/
class MysqlDepaertment implements IDepaertment{
public void Insert(Depaertment depaertment) {
System.out.println("Mysql插入Depaertment");
}
public Depaertment GetDepaertment(int id) {
System.out.println("根据id从Mysql获取Depaertment");
return null;
}
}
/*
* Oracle实现
*/
class OracleDepaertment implements IDepaertment{
public void Insert(Depaertment depaertment) {
System.out.println("Oracle插入Depaertment");
}
public Depaertment GetDepaertment(int id) {
System.out.println("根据id从Oracle获取Depaertment");
return null;
}
}
//----------还没完 去Commonly.java 中看一下 还需要在Ifactory MysqlFctory OracleFactory 中添加内容 :新增++++
package abstracFactoryModel;
/*
* 抽象工厂模式:
* 提供一个创建一系列相关或相互依赖对象的接口 而无序指定他们具体的类
*
* 最大的好处就是交换产品系列 ,因为类似于 Ifactory ifactory = new MysqlFctory();
* 在一个应用中只初始化一次 这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体的工厂就可以使用不同的产品配置
* 比如说这里:把 Ifactory ifactory = new MysqlFctory(); 修改为 Ifactory ifactory = new OracleFctory();
* 后边所有的操作就会变成针对Oracle的操作 很方便
*
*
* 第二大好处是:它让具体的创建实例过程与客户端分离 客户端通过抽象接口来操作实例,
* 产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中
*
*
* 缺点:如果需求来自于增加功能那么就非常可悲了 就拿我们在Commonly2中增加Deprtment似的 需要修改好多地方 还要添加好多东西
*
*/
public class AbstracFactoryModel {
public static void main(String[] args) {
}
}
/*
* 用简单工厂模式来代替 用DataAccess 代替 Ifactory MysqlFactory OracleFactory
*
* 但是如果想再加一个类别 比如sqlsever 需要在DataAccess中加case 分支了
*
*
* 用反射!!!-->DataAccessRflect
* 可以看到DataAccessRflect 这个类中用了反射 用了反射之后 再添加新的分类是不需要添加case分支de
* 但是 但是 但是 还是需要修改个别地方的 比如说我想把mysql换成oracle 需要修改成员字段db
*怎么办???
*
*用配置文件!!!
*
*
*
*
*/
class DataAccess{
/*
* 只读属性
*/
private static String db = "mysql";
public String getDb() {
return db;
}
static IUser CreateUser(){
IUser iUser = null;
switch (db) {
case "mysql":
iUser = new MysqlUser();
case "oracle":
iUser = new OracleUser();
default:
break;
}
return iUser;
}
public static IDepaertment CreateDepartment(){
IDepaertment iDepaertment = null;
switch (db) {
case "mysql":
iDepaertment = new MysqlDepaertment();
case "oracle":
iDepaertment = new OracleDepaertment();
default:
break;
}
return iDepaertment;
}
}
class DataAccessRflect{
//包路径
private static String packagePath = "abstracFactoryModel";
//类名
private static String db = "Mysql";
static IUser CreateUser(){
IUser iUser = null;
String className = packagePath+db+"User";
try {
//这里用了反射 就不需要case分支了 如果再添加一种类型 这里是不需要改变的
iUser = (IUser) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return iUser;
}
public static IDepaertment CreateDepartment(){
IDepaertment Department = null;
String className = packagePath+db+"Department";
try {
Department = (IDepaertment) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return Department;
}
}
class DataAccessRConfig{
//包路径
private static String packagePath = "abstracFactoryModel";
//类名
static IUser CreateUser(){
IUser iUser = null;
String db = getDBfromXml();
String className = packagePath+db+"User";
try {
//这里用了反射 就不需要case分支了 如果再添加一种类型 这里是不需要改变的
iUser = (IUser) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return iUser;
}
public static IDepaertment CreateDepartment(){
IDepaertment Department = null;
String db = getDBfromXml();
String className = packagePath+db+"Department";
try {
Department = (IDepaertment) Class.forName(className).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return Department;
}
public static String getDBfromXml(){
//这里省略了从xml 或者其他配置文件中读取属性的值
//大致结构是这样 但是不同的文件有不同的标签 我这里的标签是不对的 但是结构就是这么个意思
/*<?xml version="1.0" encoding="utf-8" ?>
<configuratin>
<setting>
<add key="DB" value="Mysql">
</setting>
</configuratin>*/
return "Mysql";
}
}