• [设计模式]工厂模式(2)——工厂方法


     简介

    根据《head first 设计模式》所述,工厂模式共有三种:静态工厂方法、工厂方法、抽象工厂。本文介绍工厂方法。

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

    注:工厂方法(抽象)用来处理对象的创建,并将这样的行为封装在子类中,以将超类和子类解耦。

    具体形式如下:abstract Product factoryMethod(String type)

    其中,abstract表示工厂方法是抽象的,因此依赖子类来处理对象的创建;Product表示工厂方法必须返回一个产品,超类中定义的方法,通常使用到工厂方法的返回值;factoryMethod表示工厂方法将客户(也就是超类中的代码,例如orderPizza())和实际创建具体产品的代码分隔开来;type表示工厂方法可能需要参数也可能不需要参数来指定索要的产品。

    2、模式结构:包括创建者类(抽象创建者类和具体创建者类)和产品类(抽象产品类和具体产品类)。

    3、具体实现(完整代码)

    这里假设我们需要一个披萨系统,客户指定自己要吃的披萨种类,而每种披萨有不同的使用材料,即使使用相同的材料也是有差别的(比如说制造披萨的面团,有的是用厚的,有的是用薄的),具体的实现如下所述。

    • 抽象创建者类:定义一个抽象的工厂方法,让子类实现此方法制造产品。它通常会包含依赖于抽象产品的代码,而这些抽象产品由子类制造,创建者不需要真的知道在制造哪种具体产品。这里我们将PizzaStore作为抽象创建者类,因为可以有不同风格的披萨店,它们生产披萨的制作方法不同,因此披萨店是变动较大的部分,这里将它抽象出来,只要实现继承它的子类,就可以增加披萨店。
    //披萨店
    public abstract class PizzaStore{  
        public Pizza orderPizza(String type){
            Pizza pizza;
            pizza = createPizza(type);
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
            return pizza;
        }
        protected abstract Pizza createPizza(String type);
    }
    • 具体创建者类:用来生产具体产品的类,这里指生产披萨的店,它实现超类中的工厂方法(本例中是createPizza()方法),用来制造产品。因为每个披萨店都有自己的PizzaStore子类,因此可以利用工厂方法(createPizza()方法)创建自己风味的披萨。
    //纽约风味的披萨店
    public class NYStylePizzaStore extends PizzaStore{
        public Pizza createPizza(String item){
            if(item.equals("cheese")){
                return new NYStyleCheesePizza();
            }else if(item.equals("pepperoni")){
                return new NYStylePepperoniPizza();
            }else if(item.equals("clam")){
                return new NYStyleClamPizza();
            }else if(item.equals("veggie")){
                return new NYStyleVeggiePizza();
            }else return null;
        }
    }
    
    //芝加哥风味的披萨店
    public class ChicagoStylePizzaStore extends PizzaStore{
        public Pizza createPizza(String item){
            if(item.equals("cheese")){
                return new ChicagoStyleCheesePizza();
            }else if(item.equals("pepperoni")){
                return new ChicagoStylePepperoniPizza();
            }else if(item.equals("clam")){
                return new ChicagoStyleClamPizza();
            }else if(item.equals("veggie")){
                return new ChicagoStyleVeggiePizza();
            }else return null;
        }
    }
    
    //加利福尼亚风味的披萨店
    public class CaliforniaStylePizzaStore extends PizzaStore{
        public Pizza createPizza(String item){
            if(item.equals("cheese")){
                return new CaliforniaStyleCheesePizza();
            }else if(item.equals("pepperoni")){
                return new CaliforniaStylePepperoniPizza();
            }else if(item.equals("clam")){
                return new CaliforniaStyleClamPizza();
            }else if(item.equals("veggie")){
                return new CaliforniaStyleVeggiePizza();
            }else return null;
        }
    }
    • 抽象产品类:工厂生产的产品,对于本例来说就是披萨,即Pizza类。
    //披萨,它是我们要生产的产品
    public abstract class Pizza {
        String name;//名称
        String dough;//面团类型
        String sauce;//酱料类型
        ArrayList toppings = new ArrayList();//一套佐料
    
        void prepare(){
            System.out.println("Preparing " + name);
            System.out.println("Tossing dough...");
            System.out.println("Adding sauce... ");
            System.out.println("Adding toppings: ");
            for(int i = 0; i < toppings.size(); i++){
                System.out.println("   " + toppings.get(i));
            }
        }
    
        void bake(){
            System.out.println("Bake for 25 minutes at 350");
        }
    
        void cut(){
            System.out.println("Cutting the pizza into diagonal slices");
        }
    
        void box(){
            System.out.println("Place pizza in official PizzaStore box");
        }
    
        public String getName(){
            return name;
        }
    }
    • 具体产品类:是所有待实现的最小的元素,对于本例来说,就是具体风味的皮塞,如纽约风味的芝士披萨,或者芝加哥风味的芝士披萨等。
    //纽约风味的芝士披萨
    public class NYStyleCheesePizza extends Pizza{
        public NYStyleCheesePizza(){
            name = "NY Style Sauce and Cheese Pizza";
            dough = "Thin Crust Dough";
            sauce = "Marinara Sauce";
    
            toppings.add("Grated Reggiano Cheese");
        }
    }
    
    //芝加哥风味的芝士披萨
    public class ChicagoStyleCheesePizza extends Pizza{
        public ChicagoStyleCheesePizza(){
            name = "Chicago Style Deep Dish Cheese Pizza";
            dough = "ChicagoStyleCheese Dough";
            sauce = "ChicagoStyleCheese Sauce";
    
            toppings.add("ChicagoStyleCheese Cheese");
        }
    
        void cut(){
            System.out.println("Cutting the pizza into square slices");
        }
    }
    
    //加利福尼亚风味的芝士披萨
    public class CaliforniaStyleCheesePizza extends Pizza{
        public CaliforniaStyleCheesePizza(){
            name = "California Style Deep Dish Cheese Pizza";
            dough = "California Dough";
            sauce = "California Sauce";
    
            toppings.add("California Cheese");
        }
    
        void cut(){
            System.out.println("Cutting the pizza into square slices");
        }
    }

    测试代码:

    public class PizzaTestDrive{
        public static void main(String[] args){
            PizzaStore nyStore = new NYStylePizzaStore();
            PizzaStore chicagoStore = new ChicagoStylePizzaStore();
    
            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() + '
    ');
        }
    }

    运行结果如下图所示:

     

    4、工厂方法的优点:

    • 解耦:将产品的实现”(具体创建者类)使用”(具体使用者类)解耦,因此如果想要增加产品或者改变产品的实现,并不会对创建者有影响。
    • 具备较好的弹性和扩展性,如可以随意扩展或者更改具体产品类,即增加一个工厂或者修改一个工厂。

    5、工厂方法的缺点:

    • 工厂使用太单一,一个工厂只能生产一种产品(披萨)

    6、工厂方法和静态工厂方法的异同:

    • 工厂方法创建一个框架,让子类决定如何实现,比如本例中,orderPizza()方法提供了一般框架用来创建披萨,orderPizza()方法依赖工厂方法创建具体创建者类,并制造出实际的披萨。工厂方法具备较大的弹性,可以随意增加工厂。
    • 静态工厂方法把全部的事情在一个地方都处理完了(SimplePizzaFactory类中),且静态工厂方法不具备较好的弹性,不能变更正在创建的产品。

    参考资料

    [1] head first 设计模式

  • 相关阅读:
    Docker部署大型互联网电商平台
    大数据开发你需要知道的十个技术
    详解Linux运维工程师高级篇(大数据安全方向).
    大数据小项目之电视收视率企业项目05
    大数据小项目之电视收视率企业项目04--完全分布式搭建
    大数据小项目之电视收视率企业项目03
    大数据小项目之电视收视率企业项目02
    大数据小项目之电视收视率企业项目01
    本地Navicat连接虚拟机MySQL
    centos7安装MySQL
  • 原文地址:https://www.cnblogs.com/mj-selina/p/12488176.html
Copyright © 2020-2023  润新知