【设计模式】3种工厂模式

一、介绍

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

二、实现

1、简单工厂

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

2、工厂方法

1)工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。
2)工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

3、抽象工厂

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

三、抽象工厂具体实现

1、代码结构
在这里插入图片描述
2、package pizza
在这里插入图片描述
3、AbsFactory.java

package com.swust.pattern.创建型.工厂模式.抽象工厂;

import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.Pizza;

/**
 * @Date Created in 2022/9/16 10:24
 * @Description 抽象工厂模式抽象层
 */
public interface AbsFactory {
    // 由工厂子类实现
    Pizza createPizza(String orderType);
}

4、BJPizzaFactory.java

package com.swust.pattern.创建型.工厂模式.抽象工厂;

import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.BJCheesePizza;
import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.BJPepperPizza;
import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.Pizza;

/**
 * @Date Created in 2022/9/16 10:25
 * @Description 北京披萨工厂类
 */
public class BJPizzaFactory implements AbsFactory{
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new BJCheesePizza();
            pizza.setName("北京奶酪披萨");
        }else if(orderType.equals("pepper")){
            pizza = new BJPepperPizza();
            pizza.setName("北京胡椒披萨");
        }
        return pizza;
    }
}

5、LDPizzaFactory.java

package com.swust.pattern.创建型.工厂模式.抽象工厂;

import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.BJCheesePizza;
import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.BJPepperPizza;
import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.Pizza;

/**
 * @Date Created in 2022/9/16 10:25
 * @Description 伦敦披萨工厂类
 */
public class LDPizzaFactory implements AbsFactory{
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if(orderType.equals("cheese")){
            pizza = new BJCheesePizza();
            pizza.setName("伦敦奶酪披萨");
        }else if(orderType.equals("pepper")){
            pizza = new BJPepperPizza();
            pizza.setName("伦敦胡椒披萨");
        }
        return pizza;
    }
}

6、OrderPizza.java

package com.swust.pattern.创建型.工厂模式.抽象工厂;

import com.swust.pattern.创建型.工厂模式.抽象工厂.pizza.Pizza;

/**
 * @Date Created in 2022/9/8 9:36
 * @Description 披萨订单
 */
public class OrderPizza {

    Pizza pizza;

    public OrderPizza(AbsFactory absFactory,String orderType) {
        pizza = absFactory.createPizza(orderType);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
    }

    public Pizza getPizza() {
        return pizza;
    }
}

7、测试类

package com.swust.pattern.创建型.工厂模式.抽象工厂;

/**
 * @Date Created in 2022/9/8 9:27
 * @Description 测试类
 */
public class AbsFactoryTest {
    public static void main(String[] args) {
        BJPizzaFactory bjPizzaFactory = new BJPizzaFactory();
        LDPizzaFactory ldPizzaFactory = new LDPizzaFactory();
        OrderPizza order = new OrderPizza(bjPizzaFactory,"cheese");
        System.out.println("bjPizzaFactory准备好的pizza:" + order.getPizza().getName());
        OrderPizza order2 = new OrderPizza(ldPizzaFactory,"pepper");
        System.out.println("ldPizzaFactory准备好的pizza:" + order2.getPizza().getName());
    }
}

8、执行结果

准备北京奶酪披萨的原材料
baking 北京奶酪披萨
cut 北京奶酪披萨
box 北京奶酪披萨
bjPizzaFactory准备好的pizza:北京奶酪披萨
准备北京胡椒披萨的原材料
baking 伦敦胡椒披萨
cut 伦敦胡椒披萨
box 伦敦胡椒披萨
ldPizzaFactory准备好的pizza:伦敦胡椒披萨

四、JDK使用到的单例模式

JDK中的Calendar类中,就使用到了简单工厂模式

private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    CalendarProvider provider =
        LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                             .getCalendarProvider();
    if (provider != null) {
        try {
            return provider.getInstance(zone, aLocale);
        } catch (IllegalArgumentException iae) {
            // fall back to the default instantiation
        }
    }

    Calendar cal = null;
    // 简单工厂模式
    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;
            }
        }
    }
    if (cal == null) {
        // If no known calendar type is explicitly specified,
        // perform the traditional way to create a Calendar:
        // create a BuddhistCalendar for th_TH locale,
        // a JapaneseImperialCalendar for ja_JP_JP locale, or
        // a GregorianCalendar for any other locales.
        // NOTE: The language, country and variant strings are interned.
        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);
        }
    }
    return cal;
}

五、工厂模式小结

1)工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
2)三种工厂模式
3)设计模式的依赖抽象原则
创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。
不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
不要覆盖基类中已经实现的方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值