设计模式之四:工厂模式(简单工厂、工厂方法、抽象工厂)

                     《Head First设计模式》第四章学习笔记

一、设计原则

   要依赖抽象,不要依赖具体类。当你直接实例化一个对象时,就是在依赖它的具体类。

   如果有一个不像是会改变的类,那么在代码中直接实例化具体类也就没什么大碍。

二、工厂模式

<一>、简单工厂模式

   简单工厂模式:就是由一个类的方法(可以是静态方法)根据传入的参数,决定创建出哪一种具体产品类的实例。
   简单工厂其实不是一个设计模式,反而比较像是一种编程习惯。类图如下:

《设计模式之四:工厂模式(简单工厂、工厂方法、抽象工厂)》

<二>、工厂方法模式

    工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

   带参数的工厂方法,称为参数化工厂方法,它可以根据传入的参数创建不同的对象。(不推荐参数化的工厂方法,因为会导致每个具体的方法实现,跟简单工厂是一样的)

    工厂方法类图如下:

《设计模式之四:工厂模式(简单工厂、工厂方法、抽象工厂)》

     抽象工厂类Creator,定义了一个创建对象的抽象方法factoryMethod,在每个具体的工厂类中,实现该方法,创建具体的产品实例。

<三>、抽象工厂模式

    抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不明确指定具体类。类图如下:

《设计模式之四:工厂模式(简单工厂、工厂方法、抽象工厂)》

    抽象工厂的每个方法,实际上看起来就是工厂方法。

三、例子

1、简单工厂模式的例子

披萨店做披萨,Pizza为披萨抽象类,CheesPizza、GreekPizza、ClamPizza等为具体的Pizza实现类。现在借助简单工厂模式,根据不同的参数,创建不同的披萨。代码片段如下:

简单工厂SimplePizzaFactory类:

public class SimplePizzaFactory {
    public static Pizza createPizza(String type) {
        Pizza pizza = null;
        if ("cheese".equals(type)) {
            pizza = new CheesePizza();
        } else if ("greek".equals(type)) {
            pizza = new GreekPizza();
        } else if ("clam".equals(type)) {
            pizza = new ClamPizza();
        }
        return pizza;
    }
}

PizzaStore类(客户端):

public class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza = SimplePizzaFactory.createPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

测试代码:

public class PizzaTestDrive {
    public static void main(String[] args) {
        PizzaStore store = new PizzaStore();
        Pizza pizza = store.orderPizza("cheese");
        System.out.println("Ethan ordered a " + pizza.getName());
        pizza = store.orderPizza("clam");
        System.out.println("Joel ordered a " + pizza.getName());
    }
}

2、工厂方法模式的例子

 不同地区的披萨店,做的Pizza不一样。在工厂方法模式中,PizzaStore负责定义创建Pizza的方法,但方法的具体实现,由各个地区的披萨店来实现,并负责创建具体的Pizza。

抽象的工厂类:

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    // 抽象的方法,由各个子类来实现。此处用的是参数化的工厂方法
    protected abstract Pizza createPizza(String type);
}

具体的工厂类:

public class ChicagoPizzaStore extends PizzaStore {
    protected Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new ChicagoStyleCheesePizza();
        }
        return null;
    }
}

具体的工厂类:

public class NYPizzaStore extends PizzaStore {
    protected Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new NYStyleCheesePizza();
        }
        return null;
    }
}

测试例子:

public class PizzaTestDrive {
    public static void main(String[] args) {
        PizzaStore nyStore = new NYPizzaStore();
        PizzaStore chicagoStore = new ChicagoPizzaStore();
        Pizza pizza = nyStore.orderPizza("cheese");
        System.out.println("Ethan ordered a " + pizza.getName());
        pizza = chicagoStore.orderPizza("cheese");
        System.out.println("Joel ordered a " + pizza.getName());
    }
}

 3、抽象工厂的例子

 

4、JDK中工厂模式的应用

简单工厂:

  • java.lang.Boolean#valueOf(String)
  • java.lang.reflect.Proxy#newProxyInstance()
  • java.lang.Class#forName()
  • java.lang.Class#newInstance()

工厂方法:

  • java.lang.Object#toString()

四、小结

1、在简单工厂模式中,一个工厂类处于对产品类实例化的中心位置上,它知道每一个产品,它决定哪一个产品类应当被实例化。这个模式的优点是允许客户端相对独立于产品创建的过程,并且在系统引入新产品的时候无需修改客户端,也就是说,它在某种程度上支持“开–闭”原则。但这个模式的缺点是对“开–闭”原则的支持力度不够,因为如果有新的产品加入到系统中去,就需要修改工厂类,将必要的逻辑加入到工厂类中。

2、在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。工厂方法模式退化后可以变得很像简单工厂模式:设想如果非常确定一个系统只需要一个具体工厂类,那么就不妨把抽象工厂给合并到具体的工厂类中。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

参考资料

1、《Head First设计模式》 2、《java与模式》 3、
JDK里的设计模式

    原文作者:江南好风景
    原文地址: https://blog.csdn.net/caihaijiang/article/details/8973406
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞