3、工厂模式
本文最后更新于25 天前,其中的信息可能已经过时,如有错误请发送邮件到2260856635@qq.com

需求:便于手机种类的扩展

  • 手机的种类很多(比如HuaWeiPhone、XiaoMiPhone等)
  • 手机的制作有prepare,production, assemble, box
  • 完成手机店订购功能。

1、传统模式

  • 手机抽象类public abstract class Phone { private String name; /** * 准备的抽象类 */ public abstract void prepare(); /** * 手机生产 */ public void production(){ System.out.println(name + "手机production"); } /** * 手机组装 */ public void assemble(){ System.out.println(name + "手机assemble"); } /** * 手机打包 */ public void box(){ System.out.println(name + "手机box"); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
  • 实体类public class HuaWeiPhone extends Phone{ @Override public void prepare() { System.out.println("准备华为手机原材料!"); } }public class XiaoMiPhone extends Phone{ @Override public void prepare() { System.out.println("准备小米手机原材料!"); } }
  • 基于方法实现public class OrderPhone { public OrderPhone() { Phone phone; String orderType; while (true){ orderType = inputType(); if (orderType.equals("huawei")){ phone = new HuaWeiPhone(); phone.setName("华为"); }else if(orderType.equals("xiaomi")){ phone = new XiaoMiPhone(); phone.setName("小米"); }else { break; } phone.prepare(); phone.production(); phone.assemble(); phone.box(); } } /** * 键盘输入类型 * @return */ public String inputType(){ Scanner scanner = new Scanner(System.in); System.out.println("请输入手机类型:"); String next = scanner.next(); return next; } }
  • 调用public class PhoneStore { public static void main(String[] args) { new OrderPhone(); } }

传统方法的优缺点

优点:比较好理解,简单易操作。

缺点:违反了设计模式的ocp 原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码.

比如我们这时要新增加一个Phone的种类(oppo Phone),就需要增加OPPOPhone类,同时也要修改OrderPhone类

改进的思路

修改代码可以接受,但是如果我们在其它的地方也有创建Phone的代码,就意味着,也需要修改,而创建Phone的代码,往往有多处。

思路:把创建Phone对象封装到一个类中,这样我们有新的Phone种类时,只需要修改该类就可,其它有创建到Phone对象的代码就不需要修改了=> 简单工厂模式

2、简单工厂模式

1、介绍

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

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

在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.

2、代码实现

  1. 新建SimpleFactorypublic class SimpleFactory { public Phone createPhone(String orderType) { Phone phone = null; if (orderType.equals("huawei")){ phone = new HuaWeiPhone(); phone.setName("华为"); }else if(orderType.equals("xiaomi")){ phone = new XiaoMiPhone(); phone.setName("小米"); } return phone; } }
  2. 修改订购手机类OrderPhonepublic class OrderPhone { /** * 键盘输入类型 * @return */ public String inputType(){ Scanner scanner = new Scanner(System.in); System.out.println("请输入手机类型:"); String next = scanner.next(); return next; } SimpleFactory simpleFactory; Phone phone = null; public OrderPhone(SimpleFactory simpleFactory){ setSimpleFactory(simpleFactory); } public void setSimpleFactory(SimpleFactory simpleFactory){ String orderType; //设置简单工厂对象 this.simpleFactory = simpleFactory; do { orderType = inputType(); phone = this.simpleFactory.createPhone(orderType); if (phone != null) { phone.prepare(); phone.production(); phone.assemble(); phone.box(); }else { System.out.println("订购失败"); break; } }while (true); } }
  3. 修改调用类public class PhoneStore { public static void main(String[] args) { // new OrderPhone(); new OrderPhone(new SimpleFactory()); } }

3、工厂方法模式

新的需求:

订购不同种类的、不同厂家的手机

思路

  1. 使用简单工厂模式,创建不同的远程工厂,这样也是可以的,之前简单工厂模式就实现了,但考虑到项目的规模,以及软件的维护性,可扩展性并不是特别好
  2. 使用工厂方法模式

1、工厂方法模式介绍

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

思路:

将创建的过程写成抽象类和抽象方法

步骤

  1. 将订购手机的类变成抽象类,抽象方法为创建手机public abstract class OrderPhone { /** * 键盘输入类型 * @return */ public String inputType(){ Scanner scanner = new Scanner(System.in); System.out.println("请输入手机类型:"); String next = scanner.next(); return next; } abstract Phone createPhone(String orderType); public OrderPhone(){ Phone phone; String orderType; do { orderType = inputType(); //抽象方法,由工厂子类完成 phone = createPhone(orderType); phone.prepare(); phone.production(); phone.assemble(); phone.box(); }while (true); } public static void main(String[] args) { new DomesticPhone(); } }
  2. 分类手机,继承抽象类public class DomesticPhone extends OrderPhone{ @Override Phone createPhone(String orderType) { Phone phone = null; if (orderType.equals("huawei")){ phone = new HuaWeiPhone(); phone.setName("华为"); }else if (orderType.equals("xiaomi")){ phone = new XiaoMiPhone(); phone.setName("小米"); } return phone; } }public class IPhone extends OrderPhone{ @Override Phone createPhone(String orderType) { Phone phone = null; if (orderType.equals("pingguo")){ phone = new PingGuoPhone(); phone.setName("苹果"); }else if (orderType.equals("sanxing")){ phone = new SanXingPhone(); phone.setName("三星"); } return phone; } }

4、抽象工厂模式

定义了一个interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类

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

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

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

  1. 定义接口,让子类工厂进行实现public interface AbstractFactory { /** * 建Phone,让工厂子类实现 * @param orderType 类型 * @return phone */ public Phone createPhone(String orderType); }
  2. 子类工厂实现接口public class DomesticPhoneFactory implements AbstractFactory { @Override public Phone createPhone(String orderType) { Phone phone = null; System.out.println("~使用的是抽象工厂模式~"); if (orderType.equals("huawei")){ phone = new HuaWeiPhone(); phone.setName("华为"); }else if (orderType.equals("xiaomi")){ phone = new XiaoMiPhone(); phone.setName("小米"); } return phone; } }public class ForeignPhoneFactory implements AbstractFactory { @Override public Phone createPhone(String orderType) { Phone phone = null; if (orderType.equals("pingguo")){ phone = new PingGuoPhone(); phone.setName("苹果"); }else if (orderType.equals("sanxing")){ phone = new SanXingPhone(); phone.setName("三星"); } return phone; } }
  3. 具体调用实现public class OrderPhone { AbstractFactory factory; /** * 键盘输入类型 * @return */ public String inputType(){ Scanner scanner = new Scanner(System.in); System.out.println("请输入手机类型:"); String next = scanner.next(); return next; } public OrderPhone(AbstractFactory factory){ setFactory(factory); } private void setFactory(AbstractFactory factory){ Phone phone; String orderType; this.factory = factory; do { orderType = inputType(); //抽象工厂方法 phone = factory.createPhone(orderType); if (phone != null) { phone.prepare(); phone.production(); phone.assemble(); phone.box(); }else { System.out.println("订购失败!"); break; } }while (true); } public static void main(String[] args) { new OrderPhone(new DomesticPhoneFactory()); } }

5、工厂模式在JDK-Calendar 应用的源码分析

public class FactoryTest {

    public static void main(String[] args) {

        Calendar cal = Calendar.getInstance();
        // 注意月份下标从0 开始,所以取月份要+1
        System.out.println("年:" + cal.get(Calendar.YEAR));
        System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));
        System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("分:" + cal.get(Calendar.MINUTE));
        System.out.println("秒:" + cal.get(Calendar.SECOND));
    }
}
public static Calendar getInstance()
{
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}


  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;
    }

6、工厂模式小结

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

三种工厂模式:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

涉及到设计模式的依赖抽象原则

创建对象实例时,不要直接new 类, 而是把这个new 类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。

不要让类继承具体类,而是继承抽象类或者是实现interface(接口),不要覆盖基类中已经实现的方法。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇