简单工厂模式
工厂类角色Creator:工厂类在客户端的直接控制下( Create方法)创建产品对象。
抽象产品角色Product:定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
具体产品角色ConcreteProduct:定义工厂具体加工出的对象。
简单工厂模式——实现简单运算
代码一
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字A:");
String strA = sc.nextLine();
System.out.println("请输入运算符号(+、—、*、/):");
String stroper = sc.nextLine();
System.out.println("请输入数字B:");
String strB = sc.nextLine();
Operation oper = OperationFactory.createOperation(stroper.charAt(0));
oper.setNumberA(Double.parseDouble(strA));
oper.setNumberB(Double.parseDouble(strB));
System.out.println("结果是:" + oper.getResult());
}
}
abstract class Operation {
private double numberA = 0;
private double numberB = 0;
boolean flag = true;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public abstract double getResult();
}
//加法类
class OperationAdd extends Operation {
public double getResult() {
return getNumberA() + getNumberB();
}
}
//减法类
class OperationSub extends Operation {
public double getResult() {
return getNumberA() - getNumberB();
}
}
//乘法类
class OperationMul extends Operation {
public double getResult() {
return getNumberA() * getNumberB();
}
}
//除法类
class OperationDiv extends Operation {
public double getResult() {
return getNumberA() / getNumberB();
}
}
//简单运算工厂类
class OperationFactory {
public static Operation createOperation(char operate) {
Operation oper = null;
switch (operate) {
case '+':
oper = new OperationAdd();
break;
case '-':
oper = new OperationSub();
break;
case '*':
oper = new OperationMul();
break;
case '/':
oper = new OperationDiv();
break;
}
return oper;
}
}
实现二
import java.util.Scanner;
public class main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入数字A:");
String strA = sc.nextLine();
System.out.println("请输入运算符号(+、—、*、/):");
String stroper = sc.nextLine();
System.out.println("请输入数字B:");
String strB = sc.nextLine();
Operation oper = OperationFactory.createOperation(stroper.charAt(0));
oper.setNumberA(Double.parseDouble(strA));
oper.setNumberB(Double.parseDouble(strB));
System.out.println("结果是:" + oper.getResult());
}
}
abstract class Operation {
private double numberA = 0;
private double numberB = 0;
boolean flag = true;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public abstract double getResult();
}
//加法类
class OperationAdd extends Operation {
public double getResult() {
return getNumberA() + getNumberB();
}
}
//减法类
class OperationSub extends Operation {
public double getResult() {
return getNumberA() - getNumberB();
}
}
//乘法类
class OperationMul extends Operation {
public double getResult() {
return getNumberA() * getNumberB();
}
}
//除法类
class OperationDiv extends Operation {
public double getResult() {
return getNumberA() / getNumberB();
}
}
//简单运算工厂类——增加求m的n次方运算
class OperationFactory {
public static Operation createOperation(char operate) {
Operation oper = null;
switch (operate) {
case '+':
oper = new OperationAdd();
break;
case '-':
oper = new OperationSub();
break;
case '*':
oper = new OperationMul();
break;
case '/':
oper = new OperationDiv();
break;
case '^':
oper = new OperationMN();
}
return oper;
}
}
//增加求m的n次方类
class OperationMN extends Operation {
public double getResult() {
double r = 0;
double m = getNumberA();
int n = (int) getNumberB();
for (int i = 0; i <= n; i++) {
r = r * m;
}
return r;
}
}
优点:
二厂类中包含了必妥的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖
缺点:
在某种和度上违背了开放-封闭原则: 系统扩展困难,一旦添加新产品就得修改二厂类。
对工厂类过于依赖: 厂 类集中了所有产品创建逻辑,一旦不能正常二作, 整个系统都要受到影响。
工厂方法模式—简单计算器
public class main1 {
public static void main(String[] args) {
IFactory iFactory = new AddFactory();
Operation operation = iFactory.CreateOperation();
operation.setNumberA(1);
operation.setNumberB(2);
double result = operation.GetResult();
System.out.println("结果: " + result);
}
}
interface IFactory {
Operation CreateOperation();
}
//加法类工厂
class AddFactory implements IFactory {
public Operation CreateOperation() {
return new OperationAdd();
}
}
// 减法类工厂
class SubFactory implements IFactory {
public Operation CreateOperation() {
return new OperationSub();
}
}
// 乘法类工厂
class MulFactory implements IFactory {
public Operation CreateOperation() {
return new OperationMul();
}
}
// 除法类工厂
class DivFactory implements IFactory {
public Operation CreateOperation() {
return new OperationDiv();
}
}
//运算类
abstract class Operation {
private double numberA = 0;
private double numberB = 0;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public abstract double GetResult();
}
//加法类
class OperationAdd extends Operation {
public double GetResult() {
// TODO Auto-generated method stub
double result = 0;
result = getNumberA() + getNumberB();
return result;
}
}
//除法类
class OperationDiv extends Operation {
@Override
public double GetResult() {
double result = 0;
result = getNumberA() / getNumberB();
return result;
}
}
//乘法类
class OperationMul extends Operation {
@Override
public double GetResult() {
double result = 0;
result = getNumberA() * getNumberB();
return result;
}
}
//减法类
class OperationSub extends Operation {
@Override
public double GetResult() {
// TODO Auto-generated method stub
double result = 0;
result = getNumberA() - getNumberB();
return result;
}
}
抽象工厂模式—数据库访问程序
版本1:
public class main2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
User user = new User();
SqlserverUser sqlserverUser = new SqlserverUser();
sqlserverUser.Insert(user);
sqlserverUser.GetUser(1);
}
}
//用户对象
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;
}
}
//sql Server数据库操作user
class SqlserverUser {
public void Insert(User user) {
System.out.println("SQL Server中给User表添加一条记录");
}
public User GetUser(int id) {
System.out.println("SQL Server中根据id得到User表中的一条纪录");
return null;
}
}
- 分析:这里因为SqlserverUser sqlserverUser=new SqlserverUser();
- 这行代码写死在SqlServer了,即没有灵活性。 如果这里具有灵活性(多态),那么在执行 sqlserverUser.Insert(user);
- sqlserverUser.GetUser(1); 这两句代码时就不用考虑是哪个数据库了。
版本二:使用抽象工厂模式。
public class main2 {
public static void main(String[] args) {
User user = new User();
IFactory factory = new SqlServerFactory();
IUser iUser = factory.CreateUser();
iUser.InsertUser(user);
iUser.GetUser(1);
Department department = new Department();
IDepartment iDepartment = factory.createDepartment();
iDepartment.Insert(department);
iDepartment.GetDeparment(1);
}
}
//用户接口--->抽象产品A
interface IUser {
void InsertUser(User user);
User GetUser(int id);
}
//部门接口--->抽象产品B
interface IDepartment {
void Insert(Department department);
Department GetDeparment(int id);
}
//抽象工厂
interface IFactory {
IUser CreateUser();
IDepartment createDepartment();
}
//Access数据库访问--->具体工厂1
class AccessFactory implements IFactory {
@Override
public IUser CreateUser() {
return new AccessUser();// 类的实例化放在子类中,封装new AccessUser()所造成的变化
}
@Override
public IDepartment createDepartment() {
return new AccessDepartment();
}
}
//SqlServer数据库--->具体工厂2
class SqlServerFactory implements IFactory {
@Override
public IUser CreateUser() {
return new SqlserverUser();
}
@Override
public IDepartment createDepartment() {
return new SqlserverDepartment();
}
}
//具体产品类A
class SqlserverUser implements IUser {
@Override
public void InsertUser(User user) {
System.out.println("SQL Server中給User表添加一条记录");
}
@Override
public User GetUser(int id) {
System.out.println("SQL Server中根據id得到User表中的一条记录");
return null;
}
}
//具体产品类A
class AccessUser implements IUser {
@Override
public void InsertUser(User user) {
System.out.println("在Access中給User表添加一条记录");
}
@Override
public User GetUser(int id) {
System.out.println("在Access中根據id查找User表的一条记录");
return null;
}
}
//具体产品类B
class SqlserverDepartment implements IDepartment {
@Override
public void Insert(Department department) {
System.out.println("在SQL Server中給department表新增一条记录");
}
@Override
public Department GetDeparment(int id) {
System.out.println("在SQL Server中根據id從department表中取出一条记录");
return null;
}
}
//具体产品类B
class AccessDepartment implements IDepartment {
@Override
public void Insert(Department department) {
System.out.println("在Access中給Department表新增一条记录");
}
@Override
public Department GetDeparment(int id) {
System.out.println("在Access中根據id得到department表中的一条记录");
return null;
}
}
//用户类
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;
}
}
分析:
1、在使用了抽象工厂模式后,通过IFactory factory=new SqlServerFactory();这行代码来实现数据库的切换。
2、如果要新增一个表对象(抽象产品),则需要大量的改动。
版本三:借助简单工厂改进抽象工厂
去掉原有的IFactory抽象工厂即两个具体工厂,用下面的DataAccess类来代替。
public class main2 {
public static void main(String[] args) {
User user=new User();
Department department=new Department();
IUser iUser=DataAccess.CreateUser();//直接通过DataAccess获得想要的表对象
iUser.InsertUser(user);
iUser.GetUser(1);
IDepartment iDepartment=DataAccess.CreateDepartment();
iDepartment.Insert(department);
iDepartment.GetDeparment(1);
}
}
public class DataAccess {
private static String db="Sqlserver";
// 根据db来决定实例化不同的类
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 CreateDepartment(){
IDepartment result=null;
switch (db) {
case "Sqlserver":
result=new SqlserverDepartment();
break;
case "Access":
result=new AccessDepartment();
break;
}
return result;
}
}
分析:
这样把表对象的创建放入DataAccess中,在DataAccess中通过db来判断此时是哪一个数据库,从而实例化相应的表对象,当需要修改数据库时,只需要改动db即可。
另外,在DataAccess中有大量的分支判断,代码可以通过反射进一步优化,让db变量的值在客户端被指定,而不是事前就在DataAccess中写出。
// 数据库名称
private static String db = "Sqlserver";
// 包名----》改成SqlserverDepartment等类所在的包名
private static String AssemblyName = "com.hwj.www.model15.version4.";
/*
* 根据db来决定实例化不同的类
*/
public static IUser CreateUser() throws Exception {
IUser result = null;
//通过反射来实例化相应
result = (IUser) Class.forName(AssemblyName + db + "User").newInstance();//SqlserverUser AccessUser
return result;
}
public static IDepartment CreateDepartment() throws Exception {
IDepartment result = null;
result = (IDepartment) Class.forName(AssemblyName + db + "Department").newInstance();//SqlserverDepartment AccessDepartment
return result;
}
}
工厂方法模式:
在新增一个新产品时,就要新增一个具体工厂和一个具体产品类,这样程序的拓展性就有了提高,符合了开闭原则,避免了简单工厂模式的缺点.
但是,新增产品时需要新增两个类,会增加代码量,可谓是有舍有得,具体如何要结合具体情况来使用。
抽象工厂模式:
所有工厂模式的一般形式,当抽象工厂模式退化到只有一个产品登级结构时,就变成了工厂方法模式。当工厂方法模式的工厂类只有一个时,且工厂方法为静态方法时,则又变成了简单工厂模式。
与工厂方法模式相似,抽象工厂模式隔离了具体类的生成,让客户端不清楚具体什么样的对象被创建。