基本需求:

  • 一个披萨店需要订购不同种类的披萨

传统方式:

  • 实现思路

    • 在订购类中根据用户不同的输入直接创建不同的披萨实体类进行返回
  • UML类图

  • 代码实现

    • 披萨类

      • // 抽象父类
        public abstract class Pizza { String name; public abstract void prepare(); public void bake() {
        System.out.println(this.name + "披萨烘焙中");
        } public void cut() {
        System.out.println(this.name + "披萨切割中");
        } public void box() {
        System.out.println(this.name + "披萨打包中");
        } } // 奶酪披萨 子类1
        public class CheesePizza extends Pizza { public CheesePizza(String name) {
        this.name = name;
        } @Override
        public void prepare() {
        System.out.println(this.name + "披萨准备原材料中");
        } }
        // 希腊披萨 子类2
        public class GreekPizza extends Pizza{ public GreekPizza(String name) {
        this.name = name;
        } @Override
        public void prepare() {
        System.out.println(this.name + "披萨准备原材料中");
        } }
    • 订购类

      • public class PizzaStore {
        
           public static void main(String[] args) {
        new PizzaStore().OrderPizza();
        } // 订购披萨方法 传统方式直接采用new出子类的方法进行返回对应的披萨
        public void OrderPizza() {
        Pizza pizza;
        Scanner scanner = new Scanner(System.in);
        String orderType;
        while (true) {
        System.out.println("输入披萨的种类:");
        orderType = scanner.nextLine();
        if (StringUtils.equals("cheese", orderType)) {
        pizza = new CheesePizza("cheese");
        } else if (StringUtils.equals("greek", orderType)) {
        pizza = new GreekPizza("greek");
        } else {
        System.out.println("没有该类型的披萨");
        break;
        }
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        }
        } }

缺陷及改进:

  • 在订购方法中,直接采用new出子类的方法进行返回对应的披萨,违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码
  • 如果新增加一种类型的披萨,则需要修改OrderPizza的方法实现,如果有多个创建Pizza的方法则都需要修改
  • 把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可,其它有创建Pizza对象的代码就不需要修改了——>简单工厂模式

简单工厂模式:

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

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

  • 当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式

  • 实现思路

    • 创建一个简单工厂类SimpleFactory,提供一个创建Pizza的方法,PizzaStore想要Pizza时,直接在工厂中获取即可
  • UML类图

  • 代码实现

    • // 简单工厂类 Pizza类及实现类同上
      public class SimpleFactory { // 创建Pizza的方法 可在多个地方调用,如果需要增加其他种类的Pizza则只需要修改此方法内部的实现即可,不需要调用方
      public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new CheesePizza("cheese");
      } else if (StringUtils.equals("greek", orderType)) {
      pizza = new GreekPizza("greek");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      } // 简单工厂也叫静态工厂 可直接提供静态的方法获取对象
      public static Pizza createPizza1(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new CheesePizza("cheese");
      } else if (StringUtils.equals("greek", orderType)) {
      pizza = new GreekPizza("greek");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      } }
    • public class PizzaStore {
      
         public static void main(String[] args) {
      // new PizzaStore().OrderPizza();
      new PizzaStore(new SimpleFactory());
      } private SimpleFactory simpleFactory; public PizzaStore(SimpleFactory simpleFactory) {
      this.simpleFactory = simpleFactory;
      OrderPizza();
      } private void OrderPizza() {
      Pizza pizza;
      Scanner scanner = new Scanner(System.in);
      String orderType;
      while (true) {
      System.out.println("输入披萨的种类:");
      orderType = scanner.nextLine();
      // 通过Pizza工厂获取Pizza对象
      pizza = simpleFactory.createPizza(orderType);
      if (null == pizza) {
      break;
      }
      pizza.prepare();
      pizza.bake();
      pizza.cut();
      pizza.box();
      }
      } }

工厂方法模式:

  • 在上面的基础上增加了新的需求,需要在每种pizza上加上产地,例如 北京的奶酪pizza、北京的胡椒pizza或者是伦敦的奶酪pizza、伦敦的胡椒pizza

  • 思路1:可以使用简单工厂模式,新建两个简单工厂,BJPizzaSimpleFactory和LDPizzaSimpleFactory 但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好

  • 思路2:采用工厂方法模式

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

    • 在PizzaStore中增加一个创建Pizza抽象方法,由BJPizzaStore和LDPizzaStore去实现,至此该两个子类创建的Pizza都是各自地区的
  • UML类图

  • 代码实现

    • // 含有抽象方法的抽象类
      public abstract class PizzaStore { public static void main(String[] args) {
      // 根据地区选工厂? 没品出来和创建多个简单工厂有什么好处
      String area = "BJ";
      if (area.equals("BJ")) {
      new BJPizzaStore();
      } else {
      new LDPizzaStore();
      }
      } public PizzaStore() {
      OrderPizza();
      } private void OrderPizza() {
      Pizza pizza;
      Scanner scanner = new Scanner(System.in);
      String orderType;
      while (true) {
      System.out.println("输入披萨的种类:");
      orderType = scanner.nextLine();
      // 使用抽象方法来创建Pizza,使用不同的实现类将会得到不同的披萨
      pizza = createPizza(orderType);
      if (null == pizza) {
      break;
      }
      pizza.prepare();
      pizza.bake();
      pizza.cut();
      pizza.box();
      }
      } // 创建Pizza的抽象方法 由子类实现
      public abstract Pizza createPizza(String orderType); }
    • // 子类1
      public class BJPizzaStore extends PizzaStore { @Override
      public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new BJCheesePizza("BJCheese");
      } else if (StringUtils.equals("pepper", orderType)) {
      pizza = new BJPepperPizza("BJPepper");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      }
      } // 子类2
      public class LDPizzaStore extends PizzaStore { @Override
      public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new BJCheesePizza("LDCheese");
      } else if (StringUtils.equals("pepper", orderType)) {
      pizza = new BJPepperPizza("LDPepper");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      }
      }

抽象工厂模式:

  • 抽象工厂模式定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类,可以将简单工厂模式和工厂方法模式进行整合

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

  • 实现思路

    • 创建AbsFactory( 抽象工厂) 和具体实现的工厂子类,使用时创建工厂子类即可
  • UML类图

  • 代码实现

    • // 抽象工厂类
      public interface AbsFactory { Pizza createPizza(String orderType); } // 子类1
      public class BJFactory implements AbsFactory { @Override
      public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new BJCheesePizza("BJCheese");
      } else if (StringUtils.equals("pepper", orderType)) {
      pizza = new BJPepperPizza("BJPepper");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      } } // 子类2
      public class LDFactory implements AbsFactory { @Override
      public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (StringUtils.equals("cheese", orderType)) {
      pizza = new BJCheesePizza("LDCheese");
      } else if (StringUtils.equals("pepper", orderType)) {
      pizza = new BJPepperPizza("LDPepper");
      } else {
      System.out.println("没有该类型的披萨");
      }
      return pizza;
      } }
    • public class PizzaStore {
      
         public static void main(String[] args) {
      new PizzaStore(new BJFactory());
      } private AbsFactory factory; public PizzaStore(AbsFactory factory) {
      // 在此处声明需要工厂类对象 , 使用时直接创建抽象工厂的子类对象即可
      this.factory = factory;
      OrderPizza();
      } private void OrderPizza() {
      Pizza pizza;
      Scanner scanner = new Scanner(System.in);
      String orderType;
      while (true) {
      System.out.println("输入披萨的种类:");
      orderType = scanner.nextLine();
      // 使用抽象方法来创建Pizza,使用不同的实现类将会得到不同的披萨
      pizza = factory.createPizza(orderType);
      if (null == pizza) {
      break;
      }
      pizza.prepare();
      pizza.bake();
      pizza.cut();
      pizza.box();
      }
      } }

jdk源码:

  • 在Calendar类中的getInstance()方法中有用到简单工厂模式

  • public static Calendar getInstance()
    {
    // 获取默认的zone和aLocale
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    } public static Calendar getInstance(TimeZone zone,
    Locale aLocale)
    {
    return createCalendar(zone, aLocale);
    } 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;
    // 此处使用了简单工厂模式来创建Calender对象 通过aLocale不同的后缀
    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;
    }
    }
    } ...... return cal;
    }

注意事项:

  • 意义:将实例化对象的的代码抽取出来,放到一个类中同一管理和维护,在项目中达到依赖解耦的目的,提高项目的扩展性和维护性
  • 依赖抽象原则(尽量依赖抽象的东西)
    • 创建对象时,不要使用new,而是将new的东西放在一个工厂中并返回
    • 不要让类继承一个具体的类,而是继承抽象类或者实现接口,不要覆盖基类汇总已经实现的方法

3.java设计模式之工厂模式的更多相关文章

  1. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  2. Java设计模式之工厂模式(Factory模式)介绍(转载)

    原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...

  3. Java 设计模式之工厂模式(二)

    原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...

  4. 浅析JAVA设计模式之工厂模式(二)

    1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...

  5. java设计模式2————工厂模式

    1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...

  6. java 设计模式之工厂模式与反射的结合

    工厂模式: /**  * @author Rollen-Holt 设计模式之 工厂模式  */   interface fruit{     public abstract void eat(); } ...

  7. JAVA设计模式--抽象工厂模式

    抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的 ...

  8. Java设计模式之-----工厂模式(简单工厂,抽象工厂)

    一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...

  9. Java设计模式之工厂模式(简单工厂模式+工厂方法模式)

    摘自http://blog.csdn.net/jason0539/article/details/23020989 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是 ...

  10. java设计模式之一工厂模式

    简单工厂模式是java设计模式中最简单的设计模式之一: 工厂模式是最常用的设计模式之一. 工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模 ...

随机推荐

  1. AA.Dapper升级了

    AA.Dapper基于dapper进一步封装而成的orm框架,提供增删改查.分页.事务.原生sql的功能,以满足日常的业务开发. 1.Repository层: DapperRepository类包含大 ...

  2. 洛谷P1450 [HAOI2008]硬币购物 背包+容斥

    无限背包+容斥? 观察数据范围,可重背包无法通过,假设没有数量限制,利用用无限背包 进行预处理,因为实际硬币数有限,考虑减掉多加的部分 如何减?利用容斥原理,减掉不符合第一枚硬币数的,第二枚,依次类推 ...

  3. Flutter 开发从 0 到 1(四)ListView 下拉加载和加载更多

    在<APP 开发从 0 到 1(三)布局与 ListView>我们完成了 ListView,这篇文章将做 ListView 下拉加载和加载更多. ListView 下拉加载 Flutter ...

  4. lua 1.0 源码分析 -- 1 lua 的虚拟指令

    lua的解释器拿到 lua 编写的源码,首先进行解析,就是进行词法分析和语法分析,将源码转换成 lua 的指令集,然后执行这个指令集. lua 源码: function f(val) return v ...

  5. VBScript 教程

    VBScript 教程 VB 不区分大小写 变量 普通变量 关键词声明 Dim.Public.Private 赋值动态创建 name = "hello" Option Explic ...

  6. 2016年 实验四  B2B模拟实验

    实验四  B2B模拟实验 [实验目的] ⑴.掌握B2B中供应商的供求信息发布.阿里商铺开设和订单交易等过程. ⑵.掌握B2B中采购商的采购信息的发布.交易洽谈.网上支付和收货等过程. [实验条件] ⑴ ...

  7. day50 Pyhton 前端01

    文档结构: <!-- 定义文档类型 --> <!DOCTYPE html> <!-- 文档 --> <html lang='en'> <!-- 仅 ...

  8. [wxpusher]分享一个服务器推送消息到微信上的小工具,可以用于微信推送提醒和告警。

    背景 作为一个程序员,业余搞点自己的东西很正常,一般程序员都会有一两台自己的服务器,谁叫今天xx云搞活动,明天yy云搞活动呢. 自家的服务器用来跑爬虫,跑博客,或者跑一些个人业务,但当服务有新状态,抢 ...

  9. Android ContentProvider 基本原理和使用详解

    ContentProvider(内容提供者)是 Android 的四大组件之一,管理 Android 以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他 ...

  10. spring boot:spring security+oauth2+sso+jwt实现单点登录(spring boot 2.3.3)

    一,sso的用途 ? 1,如果有多个应用系统,用户只需要登录一次就可以访问所有相互信任的应用系统. 不需要每次输入用户名称和用户密码, 也不需要创建并记忆多套用户名称和用户密码. 2,系统管理员只需维 ...