工厂设计模式

工厂设计模式的定义(what)

参考:

https://www.runoob.com/design-pattern/factory-pattern.html

https://www.runoob.com/design-pattern/abstract-factory-pattern.html

工厂: 顾名思义类似产品、食品等的一类事物生产的工厂。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象

组成:

  • 工厂 用来创建产品
  • 产品 实现不同种类的产品

image-20220220150637078

工厂设计模式的多种实现(how)

简单工厂

image-20220221171049173

特点: 将产品进行抽象

优点:实现简单, 比较容易理解

缺点: 扩展除了需要新增产品, 也需要修改工厂类。

  1. 抽象类-披萨产品类

    package com.arithmetic.gof.factory.product;
    
    /**
     * 产品-披萨
     *
     * @author mazhiyuan
     * @date 2022/02/21
     */
    public abstract class Pizza {
    
    	/**
    	 * 产品名字
    	 */
    	protected String name;
    
    	/**
    	 * 披萨的味道
    	 */
    	public abstract void pizzaTaste();
    
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
  2. 具体不同的产品类

    package com.arithmetic.gof.factory.product;
    
    /**
     * 芝士披萨
     *
     * @author mazhiyuan
     * @date 2022/02/21
     */
    public class CheesePizza extends Pizza {
    
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作芝士披萨");
    	}
    
    }package com.arithmetic.gof.factory.product;
    
    
    
    package com.arithmetic.gof.factory.product;
    
    /**
     * 希腊披萨
     *
     * @author mazhiyuan
     * @date 2022/02/21
     */
    public class GreekPizza extends Pizza {
    
       @Override
       public void pizzaTaste() {
          System.out.println(" 给制作希腊披萨");
       }
    
    }
    
    package com.arithmetic.gof.factory.product;
    
    /**
     * 胡椒披萨
     *
     * @author mazhiyuan
     * @date 2022/02/21
     */
    public class PepperPizza extends Pizza {
    
       @Override
       public void pizzaTaste() {
          System.out.println("给制作胡椒披萨");
       }
    
    }
    
  3. 制作/创建工厂类

    package com.arithmetic.gof.factory;
    
    
    import com.arithmetic.gof.factory.product.CheesePizza;
    import com.arithmetic.gof.factory.product.GreekPizza;
    import com.arithmetic.gof.factory.product.PepperPizza;
    import com.arithmetic.gof.factory.product.Pizza;
    
    /**
     * 简单的工厂/静态工厂
     *
     * @author mazhiyuan
     * @date 2022/02/21
     */
    public class SimpleFactory {
    
        public static Pizza createPizza(String orderType) {
    
            Pizza pizza = null;
    
            System.out.println("使用简单工厂模式2");
            if (orderType.equals("greek")) {
                pizza = new GreekPizza();
                pizza.setName(" 希腊披萨 ");
            } else if (orderType.equals("cheese")) {
                pizza = new CheesePizza();
                pizza.setName(" 奶酪披萨 ");
            } else if (orderType.equals("pepper")) {
                pizza = new PepperPizza();
                pizza.setName("胡椒披萨");
            }
    
            return pizza;
        }
    
    }
    
    

工厂方法

特点: 将产品进行抽象 将工厂抽象 适用于多个工厂 多种具体的产品。产品只有一个抽象抽象产品披萨。

工厂方法和简单工厂区别:

  • 简单工厂适用于 单个工厂, 工厂是一个具体的创建产品的工厂。
  • 工厂方法, 本质是在简单工厂的基础上,把工厂的创建方法也进行了抽象为接口。 适用于多个工厂,这样在多个工厂进行调用的时候, 因为中间有一个抽象层,具体的调用不需要修改。 只需要扩展工厂种类和工厂对应的产品就可以。

缺点:分类等级多了内部需要if else进行分支判断

image-20220221215454815

image-20220222105712941

说明:

  • 产品抽象 和 工厂抽象 属于抽象部分==框架
  • 北京 和 伦敦工厂 以及 北京所有披萨 和 伦敦所有披萨 属于具体的子类实现部分。

产品实现

  1. 抽象产品代码

    package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * 披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public abstract class Pizza {
    	/**
    	 * 产品名字
    	 */
    	protected String name;
    
    	/**
    	 * 披萨的味道
    	 */
    	public abstract void pizzaTaste();
    
    	/**
    	 * 集名称
    	 *
    	 * @param name 的名字
    	 */
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
    
  2. 具体的产品-北京奶酪披散

    package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * bjcheese披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class BJCheesePizza extends Pizza {
    
    	/**
    	 * 披萨的味道
    	 */
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作北京奶酪披萨");
    	}
    
    }
    
  3. 具体的产品-北京胡椒披萨

    package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * bjpepper披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class BJPepperPizza extends Pizza {
    	/**
    	 * 披萨的味道
    	 */
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作北京胡椒披萨");
    	}
    
    }
    
    
  4. 具体的产品-伦敦奶酪披萨

    package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * ldcheese披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class LDCheesePizza extends Pizza {
    
    	/**
    	 * 披萨的味道
    	 */
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作伦敦奶酪披萨");
    	}
    }
    
  5. 具体的产品-伦敦胡椒披萨

    package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * ldpepper披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class LDPepperPizza extends Pizza {
    	/**
    	 * 披萨的味道
    	 */
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作伦敦胡椒披萨");
    	}
    }package com.arithmetic.gof.factoryMethod.product;
    
    /**
     * ldpepper披萨
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class LDPepperPizza extends Pizza {
    	/**
    	 * 披萨的味道
    	 */
    	@Override
    	public void pizzaTaste() {
    
    		System.out.println("给制作伦敦胡椒披萨");
    	}
    }
    

工厂实现

  1. 抽象工厂

    package com.arithmetic.gof.factoryMethod.factory;
    
    import com.arithmetic.gof.factoryMethod.product.Pizza;
    
    /**
     * 工厂
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public abstract class Factory {
    
        /**
         * 创建披萨
         *
         * @param orderType 订单类型
         * @return {@code Pizza}
         */
        public abstract Pizza createPizza(String orderType);
    }
    
  2. 具体的工厂-北京工厂

    package com.arithmetic.gof.factoryMethod.factory;
    
    
    import com.arithmetic.gof.factoryMethod.product.BJCheesePizza;
    import com.arithmetic.gof.factoryMethod.product.BJPepperPizza;
    import com.arithmetic.gof.factoryMethod.product.Pizza;
    
    /**
     * bjpizza工厂
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class BJPizzaFactory extends Factory{
    
        /**
         * 创建披萨
         *
         * @param orderType 订单类型
         * @return {@code Pizza}
         */
        @Override
        public Pizza createPizza(String orderType) {
    
            Pizza pizza = null;
            if(orderType.equals("cheese")) {
                pizza = new BJCheesePizza();
            } else if (orderType.equals("pepper")) {
                pizza = new BJPepperPizza();
            }
            return pizza;
        }
    }
    
  3. 具体的工厂-伦敦工厂

    package com.arithmetic.gof.factoryMethod.factory;
    
    import com.arithmetic.gof.factoryMethod.product.LDCheesePizza;
    import com.arithmetic.gof.factoryMethod.product.LDPepperPizza;
    import com.arithmetic.gof.factoryMethod.product.Pizza;
    
    /**
     * ldpizza工厂
     *
     * @author mazhiyuan
     * @date 2022/02/22
     */
    public class LDPizzaFactory extends Factory{
        /**
         * 创建披萨
         *
         * @param orderType 订单类型
         * @return {@code Pizza}
         */
        @Override
        public Pizza createPizza(String orderType) {
    
            Pizza pizza = null;
            if(orderType.equals("cheese")) {
                pizza = new LDCheesePizza();
            } else if (orderType.equals("pepper")) {
                pizza = new LDPepperPizza();
            }
            return pizza;
        }
    }
    
    

工厂方法使用

package com.arithmetic.gof.factoryMethod;

import com.arithmetic.gof.factoryMethod.factory.BJPizzaFactory;
import com.arithmetic.gof.factoryMethod.factory.Factory;
import com.arithmetic.gof.factoryMethod.factory.LDPizzaFactory;

public class FactoryMethodMain {

    public static void main(String[] args) {

        Factory factory = new BJPizzaFactory();
        factory.createPizza("cheese").pizzaTaste();

        factory = new LDPizzaFactory();
        factory.createPizza("cheese").pizzaTaste();
    }
}

抽象工厂

特点: 抽象的工厂覆盖更广, 抽象的工厂可以创建多个抽象的产品,即多个类别的产品。

抽象工厂和工厂方法的区别:

  • 工厂方法创建一类抽象产品(如以上实现披萨) , 抽象工厂可以创建多类产品, 多等级产品。
  • 工厂方法内部只有抽象一个创建方法, 抽象工厂内部有多个抽象的创建方法
  • 工厂方法适用于单一产品, 抽象工厂适用于复杂的产品, 系列产品, 产品簇。
  • 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品

抽象工厂的组成:

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
  2. 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。

参考

设计模式——抽象工厂 - 知乎 (zhihu.com)

抽象工厂模式(详解版) (biancheng.net)

产品实现

  1. 抽象产品1

    interface Product1 {
        public void show();
    }
    
  2. 具体产品1.1

    class ConcreteProduct11 implements Product1 {
    		public void show(){
          
        }
    }
    
  3. 具体产品1.2

    class ConcreteProduct12 implements Product1 {
    		public void show(){
          
        }
    }
    
  4. 抽象产品2

    interface Product2 {
        public void show();
    }
    
  5. 具体产品2.1

    class ConcreteProduct21 implements Product2 {
    		public void show(){
          
        }
    }
    
  6. 具体产品2.2

    class ConcreteProduct22 implements Product2 {
    		public void show(){
          
        }
    }
    

工厂实现

  1. 抽象工厂

    interface AbstractFactory {
        public Product1 newProduct1();
        public Product2 newProduct2();
    }
    
  2. 具体工厂1

    class ConcreteFactory1 implements AbstractFactory {
        public Product1 newProduct1() {
            System.out.println("具体工厂 1 生成-->具体产品 11...");
            return new ConcreteProduct11();
        }
        public Product2 newProduct2() {
            System.out.println("具体工厂 1 生成-->具体产品 21...");
            return new ConcreteProduct21();
        }
    }
    
  3. 具体工厂2

    class ConcreteFactory2 implements AbstractFactory {
        public Product1 newProduct1() {
            System.out.println("具体工厂 2 生成-->具体产品 12...");
            return new ConcreteProduct12();
        }
        public Product2 newProduct2() {
            System.out.println("具体工厂 2 生成-->具体产品 22...");
            return new ConcreteProduct22();
        }
    }
    
  4. 使用

工厂设计模式总结

本质: 工厂设计模式本质是用来解决 产品创建的问题。 多种工厂类型的设计模式, 主要是围绕 单一产品 和 多种产品/多等级的产品问题进行的处理。多等级多种类的产品也可以使用简单工厂/工厂方法进行创建, 但是内部需要使用if else 进行判断。

posted @ 2022-02-23 15:38  非学无以致疑  阅读(52)  评论(0)    收藏  举报