直接new一个对象是最简单的创建对象的方式,但大量出现在业务代码中会带来至少两个问题。1:创建对象的细节直接暴露在业务代码中,修改实现细节必须修改相关的大量客户端代码。2:直接面向具体类型编程,违反了面向接口编程的原则,系统进行扩展时也不得不进行大量修改。要使得系统具有的良好的可扩展性以及后期易于维护,必须实现对产品的获取和对产品的使用解耦。要做到这两点,首先要对客户端代码屏蔽掉创建产品的细节,其次,客户端必须面向产品的抽象编程,利用java的多态特性在运行时才确定具体的产品。而这,正式本篇我们要讲的工厂模式的关键。工厂模式根据创建的产品特性又可以分为工厂方法模式和抽象工厂模式,下面我们就详细讲讲它们的特点以及区别。
2.工厂方法模式 2.1工厂方法模式的定义定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
2.2工厂方法的类结构 2.3实现创建抽象产品接口
public interface Product { void doSome(); }创建产品1
public class ConcreteProduct1 implements Product { @Override public void doSome() { System.out.println("ConcreteProduct1"); } }创建产品2
public class ConcreteProduct2 implements Product { @Override public void doSome() { System.out.println("ConcreteProduct2"); } }创建产品3
public class ConcreteProduct3 implements Product { @Override public void doSome() { System.out.println("ConcreteProduct3"); } }创建抽象工厂类
public abstract class AbstractFactory { public abstract Product createProduct(); }创建工厂类1,生产产品1
public class ProductFactory1 extends AbstractFactory { @Override public Product createProduct() { return new ConcreteProduct1(); } }创建工厂类2,生产产品2
public class ProductFactory1 extends AbstractFactory { @Override public Product createProduct() { return new ConcreteProduct1(); } }创建工厂类3,生产产品3
public class ProductFactory3 extends AbstractFactory { @Override public Product createProduct() { return new ConcreteProduct3(); } }测试
public class TestCase { public static void main(String[] args) { AbstractFactory factory=new ProductFactory1(); Product product = factory.createProduct(); product.doSome(); } }结果
这里只要将父类引用指向不同的工厂实现,就可以获得不同的产品类型,下面代码是通过工厂1创建了常品1,要想创建其他产品只要new 出不同的工厂就行,其他代码都不用变。咦?怎么还是需要new,这和直接new一个产品有区别吗?这里为了作演示进行了简化,实际上我们如果创建对象还必须进行一系列初始化操作,这些如果写在客户端代码里对以后维护和扩展来说简直是灾难,而现在所有这些都在客户端代码里被屏蔽了。其次如果使用过Spring框架的话就知道,对于工厂这种实例,我们可以交给框架帮我们创建并注入到所需的地方,而这时候你想要在客户端代码中获取不同的产品实例只需要修改下框架的配置参数,实现了和业务代码的完全解耦,为以后产品的扩展带来了极大的方便。
3.简单工厂模式简单工厂模式,顾名思义,是对工厂方法模式的简化。简单工厂模式将对所有产品的创建过程都封装在一个方法中。因为其只有一个工厂的实现类,连抽象工厂都可以省了。下面是简单工厂模式的一种实现
public class SimpleFactory { public static <T extends Product> Product createProduct(Class<T> clazz){ if(clazz.equals(ConcreteProduct1.class)){ return new ConcreteProduct1(); }else if(clazz.equals(ConcreteProduct2.class)){ return new ConcreteProduct2(); }else if(clazz.equals(ConcreteProduct3.class)){ return new ConcreteProduct3(); } throw new IllegalArgumentException("参数错误!"); } }因为方法是静态的,连工厂创建都省了,代码也很清晰,根据方法的参数选择实例化哪个产品类。那么简单工厂模式相比工厂方法模式有哪些缺点和优点呢?
优点
实现简单,类结构清晰
缺点
产品扩展困难,不符合开闭原则
工厂方法模式要增加一种产品实现时,只要添加产品类和对应的工厂类,几乎不用改变原有代码。而工厂方法模式则需要修改工厂方法,添加一种创建产品的逻辑,修改了原有代码,不符合开闭原则。
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
4.2抽象工厂模式的类结构