设计模式之工厂模式

工厂模式介绍

工厂模式属于设计模式中的创建型模式。工厂模式提供了一种最佳的创建对象的方式。工厂模式从简单到复杂有三种:简单工厂、工厂方法、抽象工厂。

举例

从一个奶酪的制作到订购的例子开始分析,我们需要集成披萨制作流程,并且声明出披萨的种类。然后再有订购的流程,先写一个不使用设计模式的例子。

package com.lesson4.factory.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:36
 */
public abstract class Pizza
{
    protected String name;

    public void setName(String name)
    {
        this.name = name;
    }

    //准备原材料
    public abstract void prepare();

    //烘烤
    public void bake()
    {
        System.out.println(name + " baking;");
    }

    //切割
    public void cut()
    {
        System.out.println(name + " cutting;");
    }

    //打包
    public void box()
    {
        System.out.println(name + " boxing;");
    }
}

准备两种pizza

package com.lesson4.factory.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:40
 */
public class GreekPizza extends Pizza
{
    @Override
    public void prepare()
    {
        System.out.println("给希腊披萨准备原材料");
    }
}

package com.lesson4.factory.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:39
 */
public class CheesePizza extends Pizza
{
    @Override
    public void prepare()
    {
        System.out.println("准备奶酪原材料");
    }
}

订购pizza

package com.lesson4.factory.pizzastore.order;

import com.lesson4.factory.pizzastore.pizza.CheesePizza;
import com.lesson4.factory.pizzastore.pizza.GreekPizza;
import com.lesson4.factory.pizzastore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:42
 */
public class OrderPizza
{
    public OrderPizza()
    {
        Pizza pizza = null;
        String orderType;
        do{
            orderType = getType();
            if(orderType.equals("greek")){
                pizza = new GreekPizza();
                pizza.setName("希腊披萨");
            } else if(orderType.equals("cheese")){
                pizza = new CheesePizza();
                pizza.setName("奶酪披萨");
            } else {
                break;
            }
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
        }while (true);
    }

    private String getType(){
        try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String line = reader.readLine();
            return line;
        } catch (IOException e)
        {
            e.printStackTrace();
            return "";
        }
    }
}

客户端

package com.lesson4.factory.pizzastore.order;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:51
 */
public class PizzaStore
{
    public static void main(String[] args)
    {
        new OrderPizza();
    }
}

从上面这个例子可以分析,没有使用设计模式他的优势在于简单,但是劣势在于耦合度太高,而且在OrderPizza类中可能会存在大量判断的现象。

简单工厂模式

  1. 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式

  2. 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)

  3. 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
    对上面的代码进行部分修改,添加SimpleFactory

package com.lesson4.factory.pizzastore.order;

import com.lesson4.factory.pizzastore.pizza.CheesePizza;
import com.lesson4.factory.pizzastore.pizza.GreekPizza;
import com.lesson4.factory.pizzastore.pizza.Pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 14:31
 */
public class SimpleFactory
{
    public Pizza createPizza(String orderType){
        Pizza pizza = null;
        if(orderType.equals("greek")){
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if(orderType.equals("cheese")){
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        }
        return pizza;
    }
}

OrderPizza修改

package com.lesson4.factory.pizzastore.order;

import com.lesson4.factory.pizzastore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:42
 */
public class OrderPizza
{
    public OrderPizza(SimpleFactory simpleFactory)
    {
        setSimpleFactory(simpleFactory);
    }

    SimpleFactory simpleFactory;
    Pizza pizza = null;

    public void setSimpleFactory(SimpleFactory simpleFactory)
    {
        String orderType = "";
        this.simpleFactory = simpleFactory;
        do
        {
            orderType = getType();
            pizza = this.simpleFactory.createPizza(orderType);
            if (pizza != null)
            {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else
            {
                System.out.println("订购失败!");
            }
        } while (true);
    }

    private String getType()
    {
        try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String line = reader.readLine();
            return line;
        } catch (IOException e)
        {
            e.printStackTrace();
            return "";
        }
    }
}

工厂方法模式

首先依然定义一个抽象的Pizza类

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:36
 */
public abstract class Pizza
{
    protected String name;

    public void setName(String name)
    {
        this.name = name;
    }

    public abstract void prepare();

    public void bake()
    {
        System.out.println(name + " baking;");
    }

    public void cut()
    {
        System.out.println(name + " cutting;");
    }

    public void box()
    {
        System.out.println(name + " boxing;");
    }
}

然后出四种口味pizza

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:23
 */
public class BJCheesePizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("北京奶酪pizza");
        System.out.println("给北京奶酪pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:26
 */
public class BJHuJiaoPizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("北京胡椒pizza");
        System.out.println("给北京胡椒pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:28
 */
public class LDCheesePizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("伦敦奶酪pizza");
        System.out.println("给伦敦奶酪pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:27
 */
public class LDHujiaoPizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("伦敦胡椒pizza");
        System.out.println("给伦敦胡椒pizza准备原材料");
    }
}

然后是准备订购pizza,这边也是写个抽象类,构造方法写他的实现逻辑

package com.lesson4.factorymethod.pizzastore.order;

import com.lesson4.factorymethod.pizzastore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:42
 */
public abstract class OrderPizza
{
    abstract Pizza createPizza(String orderType);

    public OrderPizza()
    {
        Pizza pizza = null;
        String orderType;
        do
        {
            orderType = getType();
            pizza = createPizza(orderType);

            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);

    }


    private String getType()
    {
        try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String line = reader.readLine();
            return line;
        } catch (IOException e)
        {
            e.printStackTrace();
            return "";
        }
    }
}

准备两个继承他的子类

package com.lesson4.factorymethod.pizzastore.order;


import com.lesson4.factorymethod.pizzastore.pizza.BJCheesePizza;
import com.lesson4.factorymethod.pizzastore.pizza.BJHuJiaoPizza;
import com.lesson4.factorymethod.pizzastore.pizza.Pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:38
 */
public class BJOrderPizza extends OrderPizza
{
    @Override
    Pizza createPizza(String orderType)
    {
        Pizza pizza = null;
        if(orderType.equals("Cheese")){
            pizza = new BJCheesePizza();
        }else if(orderType.equals("Hujiao")){
            pizza = new BJHuJiaoPizza();
        }
        return pizza;
    }
}

package com.lesson4.factorymethod.pizzastore.order;

import com.lesson4.factorymethod.pizzastore.pizza.LDCheesePizza;
import com.lesson4.factorymethod.pizzastore.pizza.LDHujiaoPizza;
import com.lesson4.factorymethod.pizzastore.pizza.Pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:46
 */
public class LDOrderPizza extends OrderPizza
{
    @Override
    Pizza createPizza(String orderType)
    {
        Pizza pizza = null;
        if(orderType.equals("Cheese")){
            pizza = new LDCheesePizza();
        }else if(orderType.equals("Hujiao")){
            pizza = new LDHujiaoPizza();
        }
        return pizza;
    }
}

客户端

package com.lesson4.factorymethod.pizzastore.order;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:51
 */
public class PizzaStore
{
    public static void main(String[] args)
    {
        new BJOrderPizza();//实例北京OrderPizza
    }
}

这时候比如输入Cheese控制台会打印

input pizza 种类:
Cheese
给北京奶酪pizza准备原材料
北京奶酪pizza baking;
北京奶酪pizza cutting;
北京奶酪pizza boxing;
input pizza 种类:

根据我的理解,把pizza制作和卖看做两方,首先做pizza过程定义一个抽象类,由具体的子类去继承,order那边同样负责具体的种类的提供。

抽象工厂模式

  1. 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类

  2. 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。

  3. 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一 步的抽象)。

  4. 将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:36
 */
public abstract class Pizza
{
    protected String name;

    public void setName(String name)
    {
        this.name = name;
    }

    public abstract void prepare();

    public void bake()
    {
        System.out.println(name + " baking;");
    }

    public void cut()
    {
        System.out.println(name + " cutting;");
    }

    public void box()
    {
        System.out.println(name + " boxing;");
    }
}

然后出四种口味pizza

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:23
 */
public class BJCheesePizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("北京奶酪pizza");
        System.out.println("给北京奶酪pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:26
 */
public class BJHuJiaoPizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("北京胡椒pizza");
        System.out.println("给北京胡椒pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:28
 */
public class LDCheesePizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("伦敦奶酪pizza");
        System.out.println("给伦敦奶酪pizza准备原材料");
    }
}

package com.lesson4.factorymethod.pizzastore.pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 17:27
 */
public class LDHujiaoPizza extends Pizza
{
    @Override
    public void prepare()
    {
        setName("伦敦胡椒pizza");
        System.out.println("给伦敦胡椒pizza准备原材料");
    }
}

其实就是把pizza包下面的五个类放进去

order包下,定义一个接口

package com.lesson4.abstractfactory.pizzastore.order;

import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;

//工厂模式抽象层
public interface ABSFactory
{
    Pizza createPizza(String orderType);
}

定义工厂类实现此接口

package com.lesson4.abstractfactory.pizzastore.order;

import com.lesson4.abstractfactory.pizzastore.pizza.BJCheesePizza;
import com.lesson4.abstractfactory.pizzastore.pizza.BJHuJiaoPizza;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 18:24
 */
public class BJFactory implements ABSFactory
{
    @Override
    public Pizza createPizza(String orderType)
    {
        Pizza pizza = null;
        if(orderType.equals("Cheese")){
            pizza = new BJCheesePizza();
        }else if(orderType.equals("Hujiao")){
            pizza = new BJHuJiaoPizza();
        }
        return pizza;
    }
}

package com.lesson4.abstractfactory.pizzastore.order;

import com.lesson4.abstractfactory.pizzastore.pizza.LDCheesePizza;
import com.lesson4.abstractfactory.pizzastore.pizza.LDHujiaoPizza;
import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 18:24
 */
public class LDFactory implements ABSFactory
{
    @Override
    public Pizza createPizza(String orderType)
    {
        Pizza pizza = null;
        if(orderType.equals("Cheese")){
            pizza = new LDCheesePizza();
        }else if(orderType.equals("Hujiao")){
            pizza = new LDHujiaoPizza();
        }
        return pizza;
    }
}

package com.lesson4.abstractfactory.pizzastore.order;

import com.lesson4.abstractfactory.pizzastore.pizza.Pizza;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 18:31
 */
public class PizzaOrder
{
    ABSFactory factory;

    public PizzaOrder(ABSFactory factory){
        setFactory(factory);
    }

    public void setFactory(ABSFactory factory){
        this.factory = factory;
        Pizza pizza = null;
        String orderType="";
        do{
            orderType = getType();
            pizza = factory.createPizza(orderType);
            if(pizza !=null){
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            }else {
                System.out.println("订购失败!");
                break;
            }
        }while (true);
    }

    private String getType()
    {
        try
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String line = reader.readLine();
            return line;
        } catch (IOException e)
        {
            e.printStackTrace();
            return "";
        }
    }
}

客户端

package com.lesson4.abstractfactory.pizzastore.order;

/**
 * @author 朝花不迟暮
 * @version 1.0
 * @date 2020/8/27 11:51
 */
public class PizzaStore
{
    public static void main(String[] args)
    {
        new PizzaOrder(new BJFactory());
    }
}

小结

一、工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统-管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

二、三种工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)

三、设计模式的依赖抽象原则:
➢创建对象实例时,不要直接new类,而是把这个new类的动作放在-个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。
➢不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
➢不要覆盖基类中已经实现的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值