工厂模式

定义

  1. 简单工厂:由一个工厂对象决定创建出产品的实例。
  2. 工厂方法:定义一个用于创建对象的接口,让使用者决定实例化哪一个类。工厂方法使一个类的实例化延迟到其使用者。
  3. 抽象工厂:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定他们具体实现类。

使用场景

  1. 简单工厂模式将对象的创建和对象的使用进行了分离,屏蔽了中间具体的产品类,让对象的使用者不需要知道对象的创建细节。比如线程池的创建,我们不需要知道ThreadPoolExecutor创建所需的参数,我们只需要直接使用ExecutorService接口就可以。
public class Executors {
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    ...
}
  1. 工厂方法也是将将对象的创建和对象的使用进行了分离,但是在使用的时候通常是将工厂接口作为参数传入。如ThreadPoolExecutor中的ThreadFactory参数,该参数可以定制线程池中线程的名字,优先级等属性。
public class ThreadPoolExecutor extends AbstractExecutorService {
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

    }
    ...
}

实现方式

工厂方法实现的代码

package com.fzsyw.test;

/**
 * 产品抽象类
 */
public abstract class Product {
    public abstract void method(); 
}

/**
 * 具体A产品
 */
public class ConcreteProductA extends Product {
    @Override
    public void method() {
        System.out.println("产品A");
    }
}

/**
 * 具体B产品
 */
public class ConcreteProductB extends Product {
    @Override
    public void method() {
        System.out.println("产品B");
    }
}

/**
 * 工厂抽象类
 */
public abstract class Factory {
    public abstract Product createProduct();
}

/**
 * 具体工厂
 */
public class ConcreteFactory extends Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

/**
 * 客户端使用
 */
public class Client {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct();
        product.method();
    }
}


public abstract class Factory {
    public abstract <T extends Product> T createProduct(String name);
}

/**
 * 通过反射的方式
 */
public class ConcreteFactory extends Factory {
    @Override
    public <T extends Product> T createProduct(String name) {
        Product  product = null;
        try {
            product= (Product) Class.forName(name).newInstance();
            
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

public class Client {
    public static void main(String[] args) {
        Factory factory = new ConcreteFactory();
        Product product = factory.createProduct("com.fzsyw.test.ConcreteProductB");
        product.method();
    }
}

/**
 * 实际中可能用ApplicationContext或者BeanFactory来获取
 */
public class ConcreteFactory extends Factory {
    @Autowired
    private ApplicationContext applicationContext;
    
    @Override
    public <T extends Product> T createProduct(String name) {
        return applicationContext.getBean(name, T.class);
    }
}

扩展与思考

  1. 工厂方法可以说是对简单工厂的升级。简单工厂适用于只有固定的几个产品,不利于扩展,它只能通过在简单工厂中添加新的方法来生产新的产品,不符合开闭原则。工厂方法则是添加了一个工厂的接口,也就是每多一个产品,就要新增一个工厂来进行维护,虽然增加扩展性,但是也带来了复杂性。
  2. 工厂模式有很多变种,如Spring的BeanFactory本身就是产生Bean的工厂,但是它结合了单例模式,默认情况产生的Bean都是单例的。
  3. JDKNumberFormat也用到了简单的工厂模式,但是做了改动,它即是工厂,也是产品(提供了产品的公共方法和抽象方法,抽象方法就由子类实现)。这种模式下,抽象工厂类可以提供通用的代码和统一的访问接口,而具体的子类可以将类的public去掉,让抽象工厂类成为唯一的对外接口。
public abstract class NumberFormat extends Format  {

    public final static NumberFormat getInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
    }

    public static NumberFormat getInstance(Locale inLocale) {
        return getInstance(inLocale, NUMBERSTYLE);
    }

    /**
        * 通用的接口,不用子类实现
        */
    public final String format(long number) {
        return format(number, new StringBuffer(),
                      DontCareFieldPosition.INSTANCE).toString();
    }

    /**
        * 特定接口,由子类实现
        */
    public abstract StringBuffer format(double number,
                                        StringBuffer toAppendTo,
                                        FieldPosition pos);
    ...
}
posted @ 2019-08-01 11:51  fzsyw  阅读(91)  评论(0编辑  收藏  举报