基本需求:

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

传统方式:

  • 实现思路

    • 在订购类中根据用户不同的输入直接创建不同的披萨实体类进行返回
  • 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. 如何检测ASP中的浏览器。NET与浏览器文件

    介绍 ASP.NET是一个用于使用Web表单.MVC.Web API和SignalR(这是官方定义)构建Web应用程序的高生产力框架.它是在.net框架上开发RESTful应用程序或使用HTML.CS ...

  2. git-代码分支管理

    1. git代码分支管理     DEV SIT UAT PET PRE PRD PROD常见环境英文缩写含义 英文缩写 英文 中文 DEV development 开发 SIT System Int ...

  3. ps 安装 ps 2017 下载 及教程(保姆式教程)

    链接:https://pan.baidu.com/s/1GJHiwmxwRApFYhyNZBCQtQ 提取码:7r6u 以上是百度网盘的地址. 1.下载解压安装前先断网在安装点击set-up 软件,之 ...

  4. kali linux 换国内源

    输入命令 vim /etc/apt/sources.list 添加国内源 #中科大deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-f ...

  5. beego和gin对比

    一.对mvc的支持 beego支持完整的mvc M:Model,beego orm,把数据库数据变成object 特性 支持go的所有类型存储 更简洁的curd风格 完整实现了健壮的ORM 支持的数据 ...

  6. 第三十五章 Linux常规练习题(二)参考答案

    一.练习题一 1.删除用户基本组shanghai03.发现无法正常删除,怎样才能将其删除掉,不能删除用户. groupdel shanghai03 移除其所属组的用户 2.打开多个xshell窗口连接 ...

  7. 使用原生js模拟jQuery选择器,实现new方法,兼容ie5

    // 考虑到兼容ie5,未使用es6语法 /* 使用方法: 在<head>标签中(需使用ready方法): <script src="./jQuery2.js"& ...

  8. java 常用快捷键及命令积累

    ctl + shift + o--->导入所需包,删掉没有被引用的包 ctl + / --->添加多行注释 ctl + \--->删除多行注释

  9. 结对项目的PS表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 60 80 Estimate 估计这个任务需要多少时间 10 ...

  10. day02初识判断和循环

    ​ 新的一天朝气满满,今天小东补充一些昨天没有涉及的新知识! if判断语句 if语句就像是常说的如果....那么,它会做判断,if语句有几种方式: #示例一:判断一是否等于一,等于则输出一等一,否则输 ...