原创

设计模式-工厂模式

简单工厂模式

  1. 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。
  2. 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为
  3. 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

定义一个披萨的抽象类:

/**
 * 将Pizza类做成抽象
 *
 * @author lzhpo
 */
public abstract class Pizza {

    /**
     * pizza名字
     */
    protected String 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");
    }

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

写三个类分别继承披萨抽象类:

public class CheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("给制作奶酪披萨,准备原材料。");
    }
}
public class GreekPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("给希腊披萨,准备原材料。");
    }
}
public class PepperPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("给制作胡椒披萨,准备原材料。");
    }
}

披萨的简单工厂:

public class SimpleFactory {

    /**
     * 方法1 - 简单工厂方式1
     *
     * 根据orderType返回对应的Pizza对象
     *
     * @param orderType orderType
     * @return pizza
     */
    public Pizza createPizza(String orderType) {

        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if ("greek".equals(orderType)) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if ("cheese".equals(orderType)) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        } else if ("pepper".equals(orderType)){
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        }
        return pizza;
    }

    /**
     * 方法1 - 简单工厂方式2 - 使用静态方法
     *
     * 根据orderType返回对应的Pizza对象
     *
     * @param orderType orderType
     * @return pizza
     */
    public static Pizza createPizza2(String orderType) {

        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if ("greek".equals(orderType)) {
            pizza = new GreekPizza();
            pizza.setName("希腊披萨");
        } else if ("cheese".equals(orderType)) {
            pizza = new CheesePizza();
            pizza.setName("奶酪披萨");
        } else if ("pepper".equals(orderType)){
            pizza = new PepperPizza();
            pizza.setName("胡椒披萨");
        }
        return pizza;
    }
}

第一种方法:

public class OrderPizza {
//    public OrderPizza() {
//        Pizza pizza = null;
//        // 订购披萨的类型
//        String orderType;
//        do {
//            orderType = getType();
//            if ("greek".equals(orderType)) {
//                pizza = new GreekPizza();
//                pizza.setName("greek");
//            } else if ("cheese".equals(orderType)) {
//                pizza = new CheesePizza();
//                pizza.setName("cheese");
//            } else if ("pepper".equals(orderType)){
//               pizza = new PepperPizza();
//               pizza.setName("pepper");
//            } else {
//                System.out.println("位置类型,已自动退出!");
//                break;
//            }
//            // 输出披萨的制作过程
//            pizza.prepare();
//            pizza.bake();
//            pizza.cut();
//            pizza.box();
//        } while (true);
//    }

    // 定义一个工厂对象
    SimpleFactory simpleFactory;

    Pizza pizza = null;

    // 构造器
    public OrderPizza(SimpleFactory simpleFactory) {
        setSimpleFactory(simpleFactory);
    }

    /**
     * 设置简单工厂
     *
     * @param simpleFactory simpleFactory
     */
    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("订购披萨失败!");
                break;
            }
        } while (true);
    }

    /**
     * 写一个方法,可以获取客户希望订购的披萨种类
     *
     * @return str
     */
    private String getType() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨的类型:");
            return bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

第二种方法:

public class OrderPizza2 {

    Pizza pizza = null;

    // 构造器
    public OrderPizza2() {
        String orderType = "";
        do {
            orderType = getType();
            // 直接使用静态方法
            pizza = SimpleFactory.createPizza2(orderType);

            if (pizza != null) {
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购披萨失败!");
                break;
            }
        } while (true);
    }

    /**
     * 写一个方法,可以获取客户希望订购的披萨种类
     *
     * @return str
     */
    private String getType() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨的类型:");
            return bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

测试使用:

public class PizzaStore {
    public static void main(String[] args) {
//        new OrderPizza();

//        new OrderPizza(new SimpleFactory());
//        System.out.println("退出程序");

        new OrderPizza2();
    }
}

运行结果:

请输入披萨的类型:
greek
使用简单工厂模式
给希腊披萨,准备原材料。
希腊披萨 baking
希腊披萨 cutting
希腊披萨 boxing
请输入披萨的类型:
cheese
使用简单工厂模式
给制作奶酪披萨,准备原材料。
奶酪披萨 baking
奶酪披萨 cutting
奶酪披萨 boxing

工厂方法模式

工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类

一样的,写一个披萨的抽象类,让子类继承:

public abstract class Pizza {

    /**
     * pizza名字
     */
    protected String 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");
    }

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

写四个子类分别继承披萨抽象类:

public class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京奶酪披萨");
        System.out.println("给北京奶酪披萨,准备原材料");
    }
}
public class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京胡椒披萨");
        System.out.println("给北京胡椒披萨,准备原材料");
    }
}
public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("伦敦胡椒披萨");
    }
}
public class LDPepperPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("北京奶酪披萨");
    }
}

写一个抽象方法工厂:

public abstract class OrderPizza {

    /**
     * 定义一个抽象方法,createPizza,让各个工厂子类自己实现
     *
     * @param orderType
     * @return
     */
    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);
    }

    /**
     * 写一个方法,可以获取客户希望订购的披萨种类
     *
     * @return str
     */
    private String getType() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨的类型:");
            return bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

写两个类分别继承工厂方法:

public class BJOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("cheese".equals(orderType)) {
            pizza = new BJCheesePizza();
        } else if ("pepper".equals(orderType)) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
public class LDOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("cheese".equals(orderType)) {
            pizza = new LDCheesePizza();
        } else if ("pepper".equals(orderType)) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

测试使用:

public class PizzaStore {
    public static void main(String[] args) {
        // 创建北京口味的各种披萨
//        new BJOrderPizza();

        // 创建伦敦口味的披萨
        new LDOrderPizza();
    }
}

运行结果:

请输入披萨的类型:
pepper
给伦敦奶酪披萨,准备原材料
伦敦奶酪披萨 baking
伦敦奶酪披萨 cutting
伦敦奶酪披萨 boxing
请输入披萨的类型:
cheese
给伦敦胡椒披萨,准备原材料
伦敦胡椒披萨 baking
伦敦胡椒披萨 cutting
伦敦胡椒披萨 boxing

抽象工厂模式

  1. 抽象工厂模式:定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
  2. 抽象工厂模式可以将简单工厂模式工厂方法模式进行整合。
  3. 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
  4. 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

披萨的抽象类:

public abstract class Pizza {

    /**
     * pizza名字
     */
    protected String 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");
    }

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

四个子类继承:

public class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京奶酪披萨");
        System.out.println("给北京奶酪披萨,准备原材料");
    }
}
public class BJPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("北京胡椒披萨");
        System.out.println("给北京胡椒披萨,准备原材料");
    }
}
public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦胡椒披萨");
        System.out.println("给伦敦胡椒披萨,准备原材料");
    }
}
public class LDPepperPizza extends Pizza {
    @Override
    public void prepare() {
        setName("伦敦奶酪披萨");
        System.out.println("给伦敦奶酪披萨,准备原材料");
    }
}

写一个披萨的抽象工厂类:

public abstract class OrderPizza {

    /**
     * 定义一个抽象方法,createPizza,让各个工厂子类自己实现
     *
     * @param orderType
     * @return
     */
    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);
    }

    /**
     * 写一个方法,可以获取客户希望订购的披萨种类
     *
     * @return str
     */
    private String getType() {
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("请输入披萨的类型:");
            return bufferedReader.readLine();
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

写两个类继承这个抽象工厂:

public class BJOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("cheese".equals(orderType)) {
            pizza = new BJCheesePizza();
        } else if ("pepper".equals(orderType)) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
public class LDOrderPizza extends OrderPizza {
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("cheese".equals(orderType)) {
            pizza = new LDCheesePizza();
        } else if ("pepper".equals(orderType)) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

测试使用:

public class PizzaStore {
    public static void main(String[] args) {
        // 创建北京口味的各种披萨
//        new BJOrderPizza();

        // 创建伦敦口味的披萨
        new LDOrderPizza();
    }
}

运行结果:

请输入披萨的类型:
pepper
给伦敦奶酪披萨,准备原材料
伦敦奶酪披萨 baking
伦敦奶酪披萨 cutting
伦敦奶酪披萨 boxing
请输入披萨的类型:
cheese
给伦敦胡椒披萨,准备原材料
伦敦胡椒披萨 baking
伦敦胡椒披萨 cutting
伦敦胡椒披萨 boxing

JDK源码中的工厂模式 - Calendar

创建一个测试类来打断点,看一下Calendar源码中使用到的工厂模式。

package com.lzhpo.factory;

import java.util.Calendar;

/**
 * JDK中的 Calendar 使用的工厂模式
 * <p>
 * @author lzhpo
 * @see Calendar#getInstance()
 */
public class CalendarDemo1 {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        System.out.println("年:" +calendar.get(Calendar.YEAR));
        // 月份下标从0开始,所以月份要+1
        System.out.println("月:" +(calendar.get(Calendar.MONTH) + 1));
        System.out.println("日:" +calendar.get(Calendar.DAY_OF_MONTH));
        System.out.println("时:" +calendar.get(Calendar.HOUR_OF_DAY));
        System.out.println("分:" +calendar.get(Calendar.MINUTE));
        System.out.println("秒:" +calendar.get(Calendar.SECOND));
    }
}

Calendar#getInstance()源代码:

使用默认时区和语言环境获取日历。

/**
 * Gets a calendar using the default time zone and locale. The
 * <code>Calendar</code> returned is based on the current time
 * in the default time zone with the default
 * {@link Locale.Category#FORMAT FORMAT} locale.
 *
 * @return a Calendar.
 */
public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

那再来看一下createCalendar方法,这就是一个简单工厂模式。

/**
 * 传入zone、aLocale
 */
private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        // 如果provider不为空的话
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        // 如果aLocale有扩展的话,就根据不同的情况返回不同的Calendar
        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        // 如果Calendar/cal为空的话
        if (cal == null) {
            //如果未明确指定未知的日历类型,
            //执行传统的创建日历的方法:
            //为th_TH语言环境创建一个BuddhaCalendar,
            //为ja_JP_JP语言环境创建一个JapaneseImperialCalendar,
            //为其他语言环境创建一个GregorianCalendar。 
            //注意:语言,国家/地区和变体字符串均已插入。
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        // 返回Calendar
        return cal;
    }

这就和我之前的那个披萨的简单工厂模式一样:

Calendar.getInstance()的类似.png%E7%9A%84%E7%B1%BB%E4%BC%BC.png)

Calendar中的createCalendar方法:

Calendar中的createCalendar方法.png

我的披萨的简单工厂模式:

Calendar.getInstance()的类似简单工厂模式.png%E7%9A%84%E7%B1%BB%E4%BC%BC%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png)

和Calendar中的createCalendar()也是一样的,简单工厂模式:

Calendar.getInstance()的简单工厂模式.png%E7%9A%84%E7%AE%80%E5%8D%95%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png)

正文到此结束
本文目录