设计模式学习笔记——抽象工厂模式

抽象工厂模式

抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

结构图


代码实现

两种抽象产品类:A和B
/**
 * 抽象产品A
 * 
 * @author xukai 2016年3月20日 下午1:47:24
 */
public abstract class AbstractProductA {


}
/**
 * 抽象产品B
 * 
 * @author xukai 2016年3月20日 下午1:47:46
 */
public abstract class AbstractProductB {

}
产品类A下的具体产品:
/**
 * A的具体产品1
 * @author xukai
 * 2016年3月20日 下午1:51:04
 */
public class ProductA1 extends AbstractProductA {

	@Override
	public String toString() {
		return "ProductA1";
	}
	
}
/**
 * A的具体产品2
 * @author xukai
 * 2016年3月20日 下午1:52:12
 */
public class ProductA2 extends AbstractProductA {

	@Override
	public String toString() {
		return "ProductA2";
	}
	
}
产品类B下的具体产品:
/**
 * B的具体产品1
 * @author xukai
 * 2016年3月20日 下午1:53:14
 */
public class ProductB1 extends AbstractProductB {

	@Override
	public String toString() {
		return "ProductB1";
	}
	
}
/**
 * B的具体产品2
 * @author xukai
 * 2016年3月20日 下午1:53:44
 */
public class ProductB2 extends AbstractProductB {

	@Override
	public String toString() {
		return "ProductB2";
	}
	
	
}
抽象工厂类:包含所有产品创建的抽象方法
/**
 * 抽象工厂接口,产品关键的抽象方法
 * @author xukai
 * 2016年3月20日 下午1:46:27
 */
public interface AbstractFactory {

	public abstract AbstractProductA createProductA();
	
	public abstract AbstractProductB createProductB();
	
}
具体工厂:生产具体的产品
/**
 * 具体工厂,创建具体产品
 * @author xukai
 * 2016年3月20日 下午1:54:37
 */
public class ConcreteFactory1 implements AbstractFactory{

	@Override
	public AbstractProductA createProductA() {
		return new ProductA1();
	}

	@Override
	public AbstractProductB createProductB() {
		return new ProductB1();
	}

}
/**
 * 具体工厂,创建具体产品
 * @author xukai
 * 2016年3月20日 下午1:55:24
 */
public class ConcreteFactory2 implements AbstractFactory {

	@Override
	public AbstractProductA createProductA() {
		return new ProductA2();
	}

	@Override
	public AbstractProductB createProductB() {
		return new ProductB2();
	}

}
客户端:
public class Client {

	public static void main(String[] args) {

		AbstractFactory factory = new ConcreteFactory1();
		System.out.println(factory.createProductA() + "," + factory.createProductB());

		factory = new ConcreteFactory2();
		System.out.println(factory.createProductA() + "," + factory.createProductB());

	}

}
控制台输出:
ProductA1,ProductB1
ProductA2,ProductB2
实例对应,如下图中的汽车制造
*两厢车和三厢车称为不同的等级结构,2.0排量两厢和2.0排量三厢称为不同的产品簇
抽象工厂和工厂方法区别:一个产品等级结构为工厂方法模式,两个或两个以上产品等级结构为抽象工厂模式。

demo

问题:实际Web开发中,经常换数据库(DB)解决Oracle和MySQL直接数据的切换问题

UML类图

代码实现
User和Department接口:
public interface IUser {

}
public interface IDepartment {

}
对应不同数据库实体类
MySQL:
public class MysqlDepartment implements IDepartment {

}
public class MysqlUser implements IUser {

}
Oracle:
public class OracleUser implements IUser {

}

public class OracleDepartment implements IDepartment {

}
抽象工厂:
public interface IFactory {

	public void createUser();
	
	public void createDepartment();
	
	public IUser getUser();
	
	public IDepartment getDepartment();
}
具体工厂:
public class OracleFactory implements IFactory {

	@Override
	public void createUser() {
		System.out.println("oracle 插入user语法");
	}

	@Override
	public void createDepartment() {
		System.out.println("oracle 插入department语法");
	}

	@Override
	public IUser getUser() {
		return new OracleUser();
	}

	@Override
	public IDepartment getDepartment() {
		return new OracleDepartment();
	}

}
public class MysqlFactory implements IFactory {

	@Override
	public void createUser() {
		System.out.println("mysql 插入user语法");
	}

	@Override
	public void createDepartment() {
		System.out.println("mysql 插入department语法");
	}

	@Override
	public IUser getUser() {
		return new MysqlUser();
	}

	@Override
	public IDepartment getDepartment() {
		return new MysqlDepartment();
	}

}
客户端:
public class Client {

	public static void main(String[] args) {
		IFactory facotry = new MysqlFactory();
		
		facotry.createUser();
		facotry.createDepartment();
		System.out.println(facotry.getUser());
		System.out.println(facotry.getDepartment());
		
		facotry = new OracleFactory();
		facotry.createUser();
		facotry.createDepartment();
		System.out.println(facotry.getUser());
		System.out.println(facotry.getDepartment());
		
	}
	
}
控制台输出:
mysql 插入user语法
mysql 插入department语法
com.edu.demo.MysqlUser@28d76d1e
com.edu.demo.MysqlDepartment@2ce62a39
oracle 插入user语法
oracle 插入department语法
com.edu.demo.OracleUser@6cd8f317
com.edu.demo.OracleDepartment@4e2c390c
可以从客户端中看出,需要什么类型的产品就创建什么类型的具体工厂。(如果这里只操作一张数据库表,如:user表,那么就是工厂方法模式)

抽象工厂模式的优点和缺点

优点:方便交换产品系列,想要实现这步操作,只需要改变具体工厂即可。

缺点:假如在上面的demo中,添加一张数据库表,那么至少要增加三个类,如:product表,需要IProduct、MysqlProduct、OracleProduct等。另外还需要修改其他的具体工厂类。
**使用工厂模式,只需要关心降低耦合的的目的是否达到**

简单工厂+反射

解决上面的缺点
UML图:

思路:通过反射,修改DataAccess中的db属性,从而判断返回哪种类型的具体类。

代码实现

public class DataAccess {

	private static String db = null;
	
	public DataAccess() {
		System.out.println("调用构造方法");
	}
	
	public IUser createUser(){
		IUser user = null;
		switch (db) {
		case "Oracle":
			user = new OracleUser();
			break;
		case "Mysql":
			user = new MysqlUser();
			break;
		}
		return user;
	}
	
	public IDepartment createDepartment(){
		IDepartment department = null;
		switch (db) {
		case "Oracle":
			department = new OracleDepartment();
			break;
		case "Mysql":
			department = new MysqlDepartment();
			break;
		}
		return department;
	}

	@Override
	public String toString() {
		return "DataAccess [" + db + "]";
	}
	
	
}
客户端使用反射操作:
public class Client {

	public static void main(String[] args) {

		Class<?> c1 = null; // 类
		Object access = null; // DataAccess对象
		Field fs = null; // 属性
		Method[] method = null; // 所有方法
		try {
			c1 = Class.forName("com.edu.DataAccess");
			fs = c1.getDeclaredField("db");
			access = c1.newInstance(); // 调用空参构造方法
			fs.setAccessible(true); // 设置可修改
			fs.set(access, "Oracle"); // db = "Oracle"
			method = c1.getDeclaredMethods();
			Object o = null;
			for (int i = 0; i < method.length; i++) {
				if (method[i].getName().equals("createUser")
						|| method[i].getName().equals("createDepartment")) {
					o = method[i].invoke(access, null); // 执行类中方法
					System.out.println(o);
				}
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

	}

}
控制台输出:
调用构造方法
com.edu.OracleUser@7d9331eb
com.edu.OracleDepartment@52ecba8






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值