# 简单工厂模式

# 简介

创建型模式,工厂模式中最简单,最好理解的一种。缺点:增加实现类需要更改工厂类,不符合开闭原则,但是通过一些变种实现,其实可以规避这种缺点。如下 “消灭swith - 2”

# 示例

public interface Product {
    void doSomeThing();
}

public class Product_A implements Product{
    @Override
    public void doSomeThing() {
        System.out.println("A do some thing");
    }
}

public class Product_B implements Product{
    @Override
    public void doSomeThing() {
        System.out.println("B do some thing");
    }
}

public class Product_C implements Product{
    @Override
    public void doSomeThing() {
        System.out.println("C do some thing");
    }
}

public final class SimpleProductFactory {

    public static Product getProduct(String type){
        switch (type){
            case "A":
                return new Product_A();
            case "B":
                return new Product_B();
            case "C":
                return new Product_C();
            default:
                return null;
        }
    }
}

# 调用

@Test
public void tt(){
    Product product_A = SimpleProductFactory.getProduct("A");
    product_A.doSomeThing();

    Product product_B = SimpleProductFactory.getProduct("B");
    product_B.doSomeThing();

    Product product_C = SimpleProductFactory.getProduct("C");
    product_C.doSomeThing();
}

# 消灭swith

public enum ProductType {
    PRODUCT_A("com.eason.design.factory.Product_A"),
    PRODUCT_B("com.eason.design.factory.Product_B"),
    PRODUCT_C("com.eason.design.factory.Product_C");

    private String implClass;
    private ProductType(String implClass){
        this.implClass = implClass;
    }

    public String getImplClass() {
        return implClass;
    }
}

public final class SimpleProductFactory2 {
    public static Product getProduct(ProductType type){
        try {
            return (Product)Class.forName(type.getImplClass()).newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }
}

# 调用

@Test
public void tt2(){
    Product product_A = SimpleProductFactory2.getProduct(ProductType.PRODUCT_A);
    product_A.doSomeThing();

    Product product_B = SimpleProductFactory2.getProduct(ProductType.PRODUCT_B);
    product_B.doSomeThing();

    Product product_C = SimpleProductFactory2.getProduct(ProductType.PRODUCT_C);
    product_C.doSomeThing();
}

# 消灭swith - 2

需要引入一个反射工具包

<!-- reflections -->
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.12</version>
</dependency>
public enum ProductType2 {
    Product_A,
    Product_B,
    Product_C;
}

public final class SimpleProductFactory3 {
    private static final String PACKAGE_NAME = "com.eason.design.factory";
    private static Map<ProductType2, Product> productMap = null;

    static {
        Reflections reflections = new Reflections(PACKAGE_NAME);
        Set<Class<? extends Product>> subClasses = reflections.getSubTypesOf(Product.class);
        if (subClasses != null && !subClasses.isEmpty()) {
            productMap = new HashMap<>(subClasses.size(), 1);
            for (Class<? extends Product> subClass : subClasses) {
                try {
                    productMap.put(ProductType2.valueOf(subClass.getSimpleName()), subClass.newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static Product getProduct(ProductType2 type){
        if(productMap == null){
            return null;
        }
        return productMap.get(type);
    }
}

# 调用

@Test
public void tt3(){
    Product product_A = SimpleProductFactory3.getProduct(ProductType2.Product_A);
    product_A.doSomeThing();

    Product product_B = SimpleProductFactory3.getProduct(ProductType2.Product_A);
    product_B.doSomeThing();

    Product product_C = SimpleProductFactory3.getProduct(ProductType2.Product_A);
    product_C.doSomeThing();
}