【设计模式系列-创建型模式篇】-工厂方法模式
工厂方法模式定义
工厂方法模式的使用频率非常高,在我们日常的开发过程中总能见到它的身影。其定义为:Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂方法模式应用场景
工厂方法模式是通过new关键字创建对象的替代品,所有需要生产对象的地方都可以使用,但是需要慎重考虑是否要增加一个工厂类进行管理,因为这势必会增加代码的复杂度。
工厂方法模式应用
/** * 抽象运算类 */ public abstract class Operation { // 两个数之间的运算 public abstract double operate(double a,double b); }
/** * 加法实现类 */ public class AddOperation extends Operation { @Override public double operate(double a, double b) { return a + b; } }
/** * 减法实现类 */ public class SubOperation extends Operation { @Override public double operate(double a, double b) { return a - b; } }
/** * 乘法实现类 */ public class MulOperation extends Operation { @Override public double operate(double a, double b) { return a * b; } }
/** * 除法实现类 */ public class DivOperation extends Operation { @Override public double operate(double a, double b) { if (b != 0){ return a/b; } return 0; } }
/** * 抽象运算工厂类 */ public abstract class AbstractOperationFactory { public abstract <T extends Operation> T createOperation(Class <T> c); }
/** * 具体工厂实现 */ public class OperationFactory extends AbstractOperationFactory { @Override public <T extends Operation> T createOperation(Class <T> c) { Operation operation = null; try { operation = (Operation) Class.forName(c.getName()).newInstance(); } catch (Exception e) { System.out.println("获取运算类异常"); } return (T) operation; } }
/** * 测试类 */ public class MainTest { @Test public void test(){ AbstractOperationFactory abstractOperationFactory = new OperationFactory(); Operation addOperation = abstractOperationFactory.createOperation(AddOperation.class); System.out.println(addOperation.operate(1,2)); Operation subOperation = abstractOperationFactory.createOperation(SubOperation.class); System.out.println(subOperation.operate(3,2)); Operation mulOperation = abstractOperationFactory.createOperation(MulOperation.class); System.out.println(mulOperation.operate(2,4)); Operation divOperatipon = abstractOperationFactory.createOperation(DivOperation.class); System.out.println(divOperatipon.operate(6,3)); } }
通过这个实例可以体验工厂方法模式的优点:
1、良好的封装性,代码结构清晰,一个对象的创建是有条件约束的,调用着需要获取一个具体的产品对象,只要知道这个产品的类名就可以了,不用知道创建对象等等艰辛过程,降低模块间的耦合。
2、良好的扩展性,在增加产品类的情况下,只要适当修改具体工厂类或扩展一个工厂类,就可以轻松拥抱变化。
3、屏蔽产品类,产品类的实现如何变化,调用者都不需要关心,只需要关心产品类的接口,只要接口不变,系统中的上层模块就不要发生变化。
4、工厂方法模式是典型的解耦框架,高层模块只需要知道产品的抽象类,其他的实现类都不用关心。
工厂方法模式扩展
简单工厂模式
一个模块需要一个工厂类,没有必要把它生产出来,使用静态的方法就可以。
/** * 具体工厂实现 */ public class OperationFactory { public static <T extends Operation> T createOperation(Class <T> c) { Operation operation = null; try { operation = (Operation) Class.forName(c.getName()).newInstance(); } catch (Exception e) { System.out.println("获取运算类异常"); } return (T) operation; } }
简单工厂模式也叫静态工厂模式,在项目开发中运用也比较多,但是该设计模式存在一个缺点就是工厂类的扩展比较困难,不符合开闭原则。
升级到多个工厂类
考虑到需要结构清晰,我们为每个产品定义一个工厂类,然后调用者去选择与哪个工厂方法关联。
/** * 抽象运算工厂类 */ public abstract class AbstractOperationFactory { public abstract Operation createOperation(); }
/** * 加法运算工厂 */ public class AddOperationFactory extends AbstractOperationFactory { @Override public Operation createOperation() { return new AddOperation(); } }
/** * 减法运算工厂 */ public class SubOperationFactory extends AbstractOperationFactory { @Override public Operation createOperation() { return new SubOperation(); } }
/** * 乘法工厂 */ public class MulOperationFactory extends AbstractOperationFactory { @Override public Operation createOperation() { return new MulOperation(); } }
/** * 除法工厂 */ public class DivOperationFactory extends AbstractOperationFactory { @Override public Operation createOperation() { return new DivOperation(); } }
这样改造完之后,结构变得简单,但是给可扩展性和可维护性带来了一定的影响。如果要扩展一个产品类,就需要建立一个相应的工厂类,这样就增加了扩展的难度,工厂类和产品类数量一致,维护时需要考虑两个对象之间的关系。