欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

简单工厂模式-工厂方法模式

程序员文章站 2024-01-10 00:00:04
...

在实际应用中,我们可以考虑使用封装、继承、多态把程序的耦合度降低。

1.简单工厂模式

例子:写一个计算器模拟程序

思路:将业务进行封装,并且进行松耦合,即不同的运算类之间互相不影响,可考虑通过继承一个类或者实现一个接口

类Operation,定义计算的统一接口

package SmpleFactory;

public class Operation {
	public double numberA=0;
	public 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 double getResult(){
		double result=0;
		return result;
	}
}

加法运算类,继承Operation类

package SmpleFactory;

public class OperationAdd extends Operation{
	public double getResult(){
		double result=numberA+numberB;
		return result;
	}
}

减法运算类,继承Operation类

package SmpleFactory;

public class OperationSub extends Operation{
	public double getResult(){
		double result=numberA-numberB;
		return result;
	}
}

这个时候可以写测试代码来测试了,但是实际应用中,到底要实例化谁,将来会不会增加实例化的对象,比如增加乘除法,开根号等运算,这是很容易变化的地方,应该考虑用一个单独的类做这个创造实例的过程,这就是工厂,即

package SmpleFactory;

public class OperationFactory {
	public static Operation creatOperation(String operate){
		Operation ope=null;
		switch(operate){
			case "+":
				ope=new OperationAdd();
				break;
			case "-":
				ope=new OperationSub();
				break;
		}
		return ope;
	}
}

最后,测试代码来测试:

package SmpleFactory;

public class operationTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Operation oper=null;
		oper=OperationFactory.creatOperation("+");
		oper.numberA=1;
		oper.numberB=2;
		double result=oper.getResult();
		System.out.println(result);
	}

}

这样,只需要输入运算符号,工厂就实例化出合适的对象,通过多态,返回父类的方式实现了计算器的结果。

当需要增加开根号功能,先增加功能类,然后去更改工厂方法,在case中增加语句判断即可。

何时选用简单工厂?如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选用简单工厂,让客户端通过工厂来获取相应的接口,而无需关心具体实现;如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多的、不相关的对象,可以把对外创建的职责集中到一个简单工厂来,从而实现集中管理和控制。

2.工厂方法模式

首先建立一个工厂接口

package FactoryMethod;

public interface IFactory {
	Operation createOperation();
}

然后加法和减法各建立一个具体工厂去实现这个接口

package FactoryMethod;

public class AddFactory implements IFactory{
	@Override
	public Operation createOperation() {
		// TODO Auto-generated method stub
		return new OperationAdd();
	}
}
package FactoryMethod;

public class SubFactory implements IFactory{

	@Override
	public Operation createOperation() {
		// TODO Auto-generated method stub
		return new OperationSub();
	}

}

进行测试

package FactoryMethod;

public class FactoryMethodTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		IFactory operFactory=new AddFactory();
		Operation oper=operFactory.createOperation();
		oper.numberA=1;
		oper.numberB=2;
		double result=oper.getResult();
		System.out.println(result);
	}

}

简单工厂模式最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

例如上述程序,客户端不用管该用哪个类的实例,只需要把+给工厂,工厂自动就给出了相应实例,客户端只要去做运算就可以了,不同的实例会实现不同的运算。

但是,要增加乘除功能,需要给工厂类的方法里case添加分支,即修改原有的类,违背了开放-封闭原则。

工厂方法模式,把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法,所有要生产具体类的工厂,就去实现这个接口,于是要增加乘除功能,就不需要更改原有的工厂类了,只需要增加此功能的运算类和相应的工厂类就可以。

工厂方法的本质也是用来选择实现的,跟简单工厂的区别在于工厂方法是把选择具体实现的功能延迟到子类去实现,如果把工厂方法中选择的实现放到父类直接实现,那就等同于简单工厂。

仔细观察发现,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,即工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行,若你想要添加功能,本来是改工厂类的,而现在是修改客户端,在实际使用中应该视场景而定。