Simple Factory - 图1

玩具代码案例 - 水果工厂

简单产品角色

IFruit

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product;
  2. public interface IFruit {
  3. }

Apple

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product;
  2. public class Apple implements IFruit {
  3. @Override
  4. public String toString() {
  5. return "I am Apple";
  6. }
  7. }

Grape

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product;
  2. public class Grape implements IFruit {
  3. @Override
  4. public String toString() {
  5. return "I am Grape";
  6. }
  7. }

Orange

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product;
  2. public class Orange implements IFruit {
  3. @Override
  4. public String toString() {
  5. return "I am Orange";
  6. }
  7. }

简单工厂角色

FruitFactory

  1. package org.gof.creational.patterns1.simplefactory.fruitfactory.creator;
  2. import org.gof.creational.patterns1.simplefactory.fruitfactory.product.Apple;
  3. import org.gof.creational.patterns1.simplefactory.fruitfactory.product.Grape;
  4. import org.gof.creational.patterns1.simplefactory.fruitfactory.product.IFruit;
  5. import org.gof.creational.patterns1.simplefactory.fruitfactory.product.Orange;
  6. // Supermarket
  7. public class FruitFactory {
  8. public static IFruit getFruit(FruitEnum fruit){
  9. if(FruitEnum.Apple.equals(fruit)){
  10. return new Apple();
  11. }else if(FruitEnum.Orange.equals(fruit)){
  12. return new Orange();
  13. }else if(FruitEnum.Grape.equals(fruit)){
  14. return new Grape();
  15. }
  16. else
  17. return null;
  18. }
  19. }

FruitEnum

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.creator;
  2. public enum FruitEnum {
  3. Apple,
  4. Orange,
  5. Grape,
  6. }

产品的消费者

FruitConsumer

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.customer;
  2. import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product.IFruit;
  3. public class FruitConsumer {
  4. public void Buy(IFruit fruit) {
  5. System.out.println(fruit);
  6. }
  7. }

不基于简单工厂模式的实现

Main

当前案例中,产品消费者需要直接与产品进行交互,需要知道存在哪些产品,需要知道如何初始化产品。未来的业务扩展:例如增加了新的水果产品,开发者需要知道如何与新增的产品交互

  1. package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.app.bad;
  2. import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.customer.FruitConsumer;
  3. import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product.Apple;
  4. import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product.Grape;
  5. import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.product.Orange;
  6. public class Main {
  7. public static void main(String[] args) {
  8. FruitConsumer fruitConsumer = new FruitConsumer();
  9. fruitConsumer.Buy(new Apple());
  10. fruitConsumer.Buy(new Grape());
  11. fruitConsumer.Buy(new Orange());
  12. }
  13. }

Console

I am Apple
I am Grape
I am Orange

基于简单工厂模式的实现

Main

当前案例中,产品消费者通过简单工厂获得产品,产品消费者无需直接与产品进行交互,无需知道存在哪些产品,无需知道如何初始化产品。未来的业务扩展:例如增加了新的水果产品,开发者仅仅需要知道如何与简单工厂交互即可,而无需知道增加了哪些产品类型。

package online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.app.good;

import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.creator.FruitEnum;
import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.creator.FruitFactory;
import online.javabook.gof.creational.patterns1.simplefactory.fruitfactory.customer.FruitConsumer;

public class Main {
    public static void main(String[] args) {

        FruitConsumer fruitConsumer = new FruitConsumer();
        fruitConsumer.Buy( FruitFactory.getFruit(FruitEnum.Apple) );
        fruitConsumer.Buy( FruitFactory.getFruit(FruitEnum.Grape) );
        fruitConsumer.Buy( FruitFactory.getFruit(FruitEnum.Orange) );
    }
}

Console

I am Apple
I am Grape
I am Orange

现实世界中简单工厂案例

线程池的构造函数如此之多,通过简单工厂屏蔽了大部分技术细节

package java.util.concurrent;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
import java.security.AccessControlException;
import sun.security.util.SecurityConstants;

/**
 * Factory and utility methods for {@link Executor}, {@link
 * ExecutorService}, {@link ScheduledExecutorService}, {@link
 * ThreadFactory}, and {@link Callable} classes defined in this
 * package. This class supports the following kinds of methods:
 *
 * <ul>
 *   <li> Methods that create and return an {@link ExecutorService}
 *        set up with commonly useful configuration settings.
 *   <li> Methods that create and return a {@link ScheduledExecutorService}
 *        set up with commonly useful configuration settings.
 *   <li> Methods that create and return a "wrapped" ExecutorService, that
 *        disables reconfiguration by making implementation-specific methods
 *        inaccessible.
 *   <li> Methods that create and return a {@link ThreadFactory}
 *        that sets newly created threads to a known state.
 *   <li> Methods that create and return a {@link Callable}
 *        out of other closure-like forms, so they can be used
 *        in execution methods requiring {@code Callable}.
 * </ul>
 *
 * @since 1.5
 * @author Doug Lea
 */
public class Executors {

    /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    ......
}