【设计模式——学习笔记(下)】23种设计模式——工厂模式Factory(原理讲解+应用场景介绍+案例介绍+Java代码实现)

简介: 【设计模式——学习笔记】23种设计模式——工厂模式Factory(原理讲解+应用场景介绍+案例介绍+Java代码实现)

抽象工厂模式(尚硅谷版本)

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

实现

【抽象工厂接口】

package com.atguigu.factory.absfactory.pizzastore.order;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;
/**
 * 一个抽象工厂模式的抽象层(接口)
 */
public interface AbsFactory {
   /**
    * 让下面的工厂子类来 具体实现
    * @param orderType
    * @return
    */
   public Pizza createPizza(String orderType);
}

【工厂子类】

package com.atguigu.factory.absfactory.pizzastore.order;
import com.atguigu.factory.absfactory.pizzastore.pizza.BJCheesePizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.BJPepperPizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;
//这是工厂子类
public class BJFactory implements AbsFactory {
   @Override
   public Pizza createPizza(String orderType) {
      System.out.println("~使用的是抽象工厂模式~");
      Pizza pizza = null;
      if(orderType.equals("cheese")) {
         pizza = new BJCheesePizza();
      } else if (orderType.equals("pepper")){
         pizza = new BJPepperPizza();
      }
      return pizza;
   }
}
package com.atguigu.factory.absfactory.pizzastore.order;
import com.atguigu.factory.absfactory.pizzastore.pizza.LDCheesePizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.LDPepperPizza;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;
public class LDFactory implements AbsFactory {
   @Override
   public Pizza createPizza(String orderType) {
      Pizza pizza = null;
      if (orderType.equals("cheese")) {
         pizza = new LDCheesePizza();
      } else if (orderType.equals("pepper")) {
         pizza = new LDPepperPizza();
      }
      return pizza;
   }
}

【订购】

package com.atguigu.factory.absfactory.pizzastore.order;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.atguigu.factory.absfactory.pizzastore.pizza.Pizza;
public class OrderPizza {
   AbsFactory factory;
   // 构造器
   public OrderPizza(AbsFactory factory) {
      setFactory(factory);
   }
   private void setFactory(AbsFactory factory) {
      Pizza pizza = null;
      String orderType = "";
      this.factory = factory;
      do {
         // 用户输入
         orderType = getType();
         // factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
         pizza = factory.createPizza(orderType);
         if (pizza != null) {
            //--if--订购ok
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();
         } else {
            System.out.println("订购失败");
            break;
         }
      } while (true);
   }
   /**
    * 写一个方法,可以获取客户希望订购的披萨种类
    * @return
    */
   private String getType() {
      try {
         BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
         System.out.println("input pizza 种类:");
         String str = strin.readLine();
         return str;
      } catch (IOException e) {
         e.printStackTrace();
         return "";
      }
   }
}

【主类】

package com.atguigu.factory.absfactory.pizzastore.order;
public class PizzaStore {
   public static void main(String[] args) {
      //new OrderPizza(new BJFactory());
      new OrderPizza(new LDFactory());
   }
}

抽象工厂模式(《图解设计模式》)

介绍
  • 抽象工厂将抽象零件组装成为抽象产品,只关心接口,不关心零件的具体实现
  • 有多个具体工厂才适合使用抽象工厂模式
案例实现

【抽象类】

package com.atguigu.factory.absfactory.Sample.factory;
/**
 * 抽象工厂
 */
public abstract class Factory {
    /**
     * 根据指定的类名生成具体工厂的实例
     * @param classname
     * @return
     */
    public static Factory getFactory(String classname) {
        Factory factory = null;
        try {
            //Class.forName动态获取类信息
            //使用newInstance()生成类的实例
            //new的是具体工厂,后面转成抽象工厂
            factory = (Factory)Class.forName(classname).newInstance();
        } catch (ClassNotFoundException e) {
            System.err.println("没有找到 " + classname + "类。");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }
    /**
     * 生成零件
     * @param caption
     * @return
     */
    public abstract Link createLink(String caption, String url);
    /**
     * 生成零件
     * @param caption
     * @return
     */
    public abstract Tray createTray(String caption);
    /**
     * 生成产品
     * @param title
     * @param author
     * @return
     */
    public abstract Page createPage(String title, String author);
}
package com.atguigu.factory.absfactory.Sample.factory;
/**
 * 项目:Link类和Tray类的父类
 */
public abstract class Item {
    /**
     * 项目标题
     */
    protected String caption;
    public Item(String caption) {
        this.caption = caption;
    }
    /**
     * 返回HTML文件的内容
     * @return
     */
    public abstract String makeHTML();
}
package com.atguigu.factory.absfactory.Sample.factory;
/**
 * 表示HTML的超链接
 * 因为Link没有实现Item的抽象方法,因此,Link也是抽象类
 */
public abstract class Link extends Item {
    protected String url;
    public Link(String caption, String url) {
        super(caption);
        this.url = url;
    }
}
package com.atguigu.factory.absfactory.Sample.factory;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
/**
 * 抽象表示HTML页面(Link和Tray可以理解为抽象零件,Page可以理解为抽象产品)
 */
public abstract class Page {
    /**
     * 页面标题
     */
    protected String title;
    /**
     * 页面字段
     */
    protected String author;
    protected ArrayList content = new ArrayList();
    public Page(String title, String author) {
        this.title = title;
        this.author = author;
    }
    public void add(Item item) {
        content.add(item);
    }
    /**
     * 1、根据页面标题确认文件名
     * 2、调用makeHTML方法将自身保存的HTML内容写入到文件中
     */
    public void output() {
        try {
            String filename = title + ".html";
            Writer writer = new FileWriter(filename);
            writer.write(this.makeHTML());
            writer.close();
            System.out.println(filename + " 编写完成。");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public abstract String makeHTML();
}
package com.atguigu.factory.absfactory.Sample.factory;
import java.util.ArrayList;
/**
 * 托盘类
 * 里面可以包含多个Link和多个Tray,可以理解为上面放置了很多项目
 * 没有实现父类的抽象方法,该类也是抽象类
 */
public abstract class Tray extends Item {
    protected ArrayList tray = new ArrayList();
    public Tray(String caption) {
        super(caption);
    }
    /**
     * 添加项目
     * @param item
     */
    public void add(Item item) {
        tray.add(item);
    }
}

【具体工厂一:创建列表形式的页面】

package com.atguigu.factory.absfactory.Sample.listfactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
/**
 * 具体工厂
 */
public class ListFactory extends Factory {
    public Link createLink(String caption, String url) {
        return new ListLink(caption, url);
    }
    public Tray createTray(String caption) {
        return new ListTray(caption);
    }
    public Page createPage(String title, String author) {
        return new ListPage(title, author);
    }
}
package com.atguigu.factory.absfactory.Sample.listfactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
public class ListLink extends Link {
    public ListLink(String caption, String url) {
        super(caption, url);
    }
    public String makeHTML() {
        return "  <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
    }
}
package com.atguigu.factory.absfactory.Sample.listfactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
import java.util.Iterator;
public class ListPage extends Page {
    public ListPage(String title, String author) {
        super(title, author);
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<html><head><title>" + title + "</title></head>\n");
        buffer.append("<body>\n");
        buffer.append("<h1>" + title + "</h1>\n");
        buffer.append("<ul>\n");
        Iterator it = content.iterator();
        while (it.hasNext()) {
            Item item = (Item) it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}
package com.atguigu.factory.absfactory.Sample.listfactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
import java.util.Iterator;
public class ListTray extends Tray {
    public ListTray(String caption) {
        super(caption);
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<li>\n");
        buffer.append(caption + "\n");
        buffer.append("<ul>\n");
        Iterator it = tray.iterator();
        while (it.hasNext()) {
            Item item = (Item) it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("</li>\n");
        return buffer.toString();
    }
}

【具体工厂二:创建表格形式的页面】

package com.atguigu.factory.absfactory.Sample.tablefactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
/**
 * 多个具体工厂
 */
public class TableFactory extends Factory {
    public Link createLink(String caption, String url) {
        return new TableLink(caption, url);
    }
    public Tray createTray(String caption) {
        return new TableTray(caption);
    }
    public Page createPage(String title, String author) {
        return new TablePage(title, author);
    }
}
package com.atguigu.factory.absfactory.Sample.tablefactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
public class TableLink extends Link {
    public TableLink(String caption, String url) {
        super(caption, url);
    }
    public String makeHTML() {
        return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
    }
}
package com.atguigu.factory.absfactory.Sample.tablefactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
import java.util.Iterator;
public class TablePage extends Page {
    public TablePage(String title, String author) {
        super(title, author);
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<html><head><title>" + title + "</title></head>\n");
        buffer.append("<body>\n");
        buffer.append("<h1>" + title + "</h1>\n");
        buffer.append("<table width=\"80%\" border=\"3\">\n");
        Iterator it = content.iterator();
        while (it.hasNext()) {
            Item item = (Item)it.next();
            buffer.append("<tr>" + item.makeHTML() + "</tr>");
        }
        buffer.append("</table>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}
package com.atguigu.factory.absfactory.Sample.tablefactory;
import com.atguigu.factory.absfactory.Sample.factory.*;
import java.util.Iterator;
public class TableTray extends Tray {
    public TableTray(String caption) {
        super(caption);                     // 使用super(...)表达式  
    }
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<td>");
        buffer.append("<table width=\"100%\" border=\"1\"><tr>");
        buffer.append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" + tray.size() + "\"><b>" + caption + "</b></td>");
        buffer.append("</tr>\n");
        buffer.append("<tr>\n");
        Iterator it = tray.iterator();
        while (it.hasNext()) {
            Item item = (Item) it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</tr></table>");
        buffer.append("</td>");
        return buffer.toString();
    }
}

【委托加工】

package com.atguigu.factory.absfactory.Sample;
import com.atguigu.factory.absfactory.Sample.factory.*;
/**
 * 使用工厂将零件组装成为产品
 * 该类没有使用任何具体零件、产品、工厂,只使用抽象的
 */
public class Main {
    public static void main(String[] args) {
        String arg = "com.atguigu.factory.absfactory.Sample.listfactory.ListFactory";
        //创建工厂
        Factory factory = Factory.getFactory(arg);
        //创建零件
        Link people = factory.createLink("人民日报", "http://www.people.com.cn/");
        Link gmw = factory.createLink("光明日报", "http://www.gmw.cn/");
        Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
        Link jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/");
        Link excite = factory.createLink("Excite", "http://www.excite.com/");
        Link google = factory.createLink("Google", "http://www.google.com/");
        Tray traynews = factory.createTray("日报");
        traynews.add(people);
        traynews.add(gmw);
        Tray trayyahoo = factory.createTray("Yahoo!");
        trayyahoo.add(us_yahoo);
        trayyahoo.add(jp_yahoo);
        Tray traysearch = factory.createTray("检索引擎");
        traysearch.add(trayyahoo);
        traysearch.add(excite);
        traysearch.add(google);
        //组装产品
        Page page = factory.createPage("LinkPage", "杨文轩");
        page.add(traynews);
        page.add(traysearch);
        page.output();
    }
}

【运行】

LinkPage.html 编写完成。
Process finished with exit code 0

生成的文件(列表形式)

<html><head><title>LinkPage</title></head>
<body>
<h1>LinkPage</h1>
<ul>
<li>
日报
<ul>
  <li><a href="http://www.people.com.cn/">人民日报</a></li>
  <li><a href="http://www.gmw.cn/">光明日报</a></li>
</ul>
</li>
<li>
检索引擎
<ul>
<li>
Yahoo!
<ul>
  <li><a href="http://www.yahoo.com/">Yahoo!</a></li>
  <li><a href="http://www.yahoo.co.jp/">Yahoo!Japan</a></li>
</ul>
</li>
  <li><a href="http://www.excite.com/">Excite</a></li>
  <li><a href="http://www.google.com/">Google</a></li>
</ul>
</li>
</ul>
<hr><address>杨文轩</address></body></html>

生成的文件(表格形式)

<html><head><title>LinkPage</title></head>
<body>
<h1>LinkPage</h1>
<table width="80%" border="3">
<tr><td><table width="100%" border="1"><tr><td bgcolor="#cccccc" align="center" colspan="2"><b>日报</b></td></tr>
<tr>
<td><a href="http://www.people.com.cn/">人民日报</a></td>
<td><a href="http://www.gmw.cn/">光明日报</a></td>
</tr></table></td></tr><tr><td><table width="100%" border="1"><tr><td bgcolor="#cccccc" align="center" colspan="3"><b>检索引擎</b></td></tr>
<tr>
<td><table width="100%" border="1"><tr><td bgcolor="#cccccc" align="center" colspan="2"><b>Yahoo!</b></td></tr>
<tr>
<td><a href="http://www.yahoo.com/">Yahoo!</a></td>
<td><a href="http://www.yahoo.co.jp/">Yahoo!Japan</a></td>
</tr></table></td><td><a href="http://www.excite.com/">Excite</a></td>
<td><a href="http://www.google.com/">Google</a></td>
</tr></table></td></tr></table>
<hr><address>杨文轩</address></body></html>

角色
  • AbstractProduct(抽象产品):负责定义抽象零件和产品的接口(API),如上面的Link、Tray、Page类
  • AbstractFactory(抽象工厂):负责定义生成抽象产品的接口(API),如上面的Factory类
  • Client(委托者):委托工厂加工产品,调用AbstractFactory 角色和AbstractProduct角色的接(API),如上面的Main类
  • ConcreteProduct(具体产品):负责实现AbstractProduct角色的接口,如上面的ListLink类、ListTray类和ListPage类;TableLink类、TableTray类和TablePage类
  • ConcreteFactory( 具体工厂):负责实现AbstractFactory角色的接口,如上面的Listfactory类、Tablefactory类

分析
  • 容易增加具体工厂:只需要编写Factory、LinkTray、Page这4个类的子类,实现抽象方法
  • 难以增加新零件:如在factory包中增加一个表示图像的Picture零件,需要在抽象工厂中增加一个createPicture的方法,所有的具体工厂都需要新增代码,具体工厂越多,工作量越大

简单工厂模式在JDK中的应用

小结

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

文章说明

  • 本文章为本人学习尚硅谷的学习笔记,文章中大部分内容来源于尚硅谷视频(点击学习尚硅谷相关课程),也有部分内容来自于自己的思考,发布文章是想帮助其他学习的人更方便地整理自己的笔记或者直接通过文章学习相关知识,如有侵权请联系删除,最后对尚硅谷的优质课程表示感谢。
  • 本人还同步阅读《图解设计模式》书籍(图解设计模式/(日)结城浩著;杨文轩译–北京:人民邮电出版社,2017.1),进而综合两者的内容,让知识点更加全面
目录
相关文章
|
2天前
|
设计模式 Java
Java设计模式:组合模式的介绍及代码演示
组合模式是一种结构型设计模式,用于将多个对象组织成树形结构,并统一处理所有对象。例如,统计公司总人数时,可先统计各部门人数再求和。该模式包括一个通用接口、表示节点的类及其实现类。通过树形结构和节点的通用方法,组合模式使程序更易扩展和维护。
Java设计模式:组合模式的介绍及代码演示
|
4天前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提高代码的可维护性与扩展性
在本文中,我们将深入探讨PHP编程语言中设计模式的重要性,以及如何通过应用这些模式来提高代码的可维护性和扩展性。设计模式是一套被反复使用、经过分类编目的代码设计经验的总结。它们代表了最佳的实践,能帮助开发者编写出更加健壮、灵活和可复用的代码。本文将介绍几种常见的设计模式,并通过PHP代码示例展示其应用。
|
21天前
|
设计模式 Java
Java 设计模式之谜:工厂模式与抽象工厂模式究竟隐藏着怎样的神奇力量?
【8月更文挑战第30天】在Java编程中,设计模式为常见问题提供了高效解决方案。工厂模式与抽象工厂模式是常用的对象创建型设计模式,能显著提升代码的灵活性、可维护性和可扩展性。工厂模式通过定义创建对象的接口让子类决定实例化哪个类;而抽象工厂模式则进一步提供了一个创建一系列相关或相互依赖对象的接口,无需指定具体类。这种方式使得系统更易于扩展和维护。
30 1
|
21天前
|
设计模式 Java
重构你的代码:探索Java中的混合、装饰器与组合设计模式
【8月更文挑战第30天】在软件开发中,设计模式为特定问题提供了结构化的解决方案,使代码更易理解、维护及扩展。本文将介绍三种常用的 Java 设计模式:混合模式、装饰器模式与组合模式,并附有示例代码展示实际应用。混合模式允许通过继承多个接口或抽象类实现多重继承;装饰器模式可在不改变对象结构的情况下动态添加新功能;组合模式则通过树形结构表示部分-整体层次,确保客户端处理单个对象与组合对象时具有一致性。
15 1
|
25天前
|
设计模式 算法 开发者
深入理解工厂模式与策略模式:设计模式的灵活应用
深入理解工厂模式与策略模式:设计模式的灵活应用
|
1月前
|
设计模式 算法 安全
Java编程中的设计模式:提升代码的可维护性和扩展性
【8月更文挑战第19天】在软件开发的世界里,设计模式是解决常见问题的一种优雅方式。本文将深入探讨Java编程语言中常用的几种设计模式,并解释如何通过这些模式来提高代码的可维护性和扩展性。文章不涉及具体的代码实现,而是侧重于理论和实践相结合的方式,为读者提供一种思考和改善现有项目的新视角。
|
1月前
|
设计模式 Java
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
文章提供了一份常用设计模式的全面介绍,包括创建型模式、结构型模式和行为型模式。每种设计模式都有详细的概念讲解、案例说明、代码实例以及运行截图。作者通过这些模式的介绍,旨在帮助读者更好地理解源码、编写更优雅的代码,并进行系统重构。同时,文章还提供了GitHub上的源码地址,方便读者直接访问和学习。
常用设计模式介绍~~~ Java实现 【概念+案例+代码】
|
1月前
|
设计模式 uml C语言
设计模式----------工厂模式之简单工厂模式(创建型)
这篇文章详细介绍了简单工厂模式,包括其定义、应用场景、UML类图、通用代码实现、运行结果、实际应用例子,以及如何通过反射机制实现对象创建,从而提高代码的扩展性和维护性。
设计模式----------工厂模式之简单工厂模式(创建型)
|
1月前
|
设计模式 uml
设计模式-------------工厂模式之工厂方法模式(创建型)
工厂方法模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而实现类的实例化推迟到子类中进行,提高了系统的灵活性和可扩展性。
|
1月前
|
设计模式 Java C语言
设计模式-----------工厂模式之抽象工厂模式(创建型)
抽象工厂模式是一种创建型设计模式,它提供了一个接口用于创建一系列相关或相互依赖的对象,而无需指定具体类,从而增强了程序的可扩展性并确保客户端只使用同一产品族的产品。
设计模式-----------工厂模式之抽象工厂模式(创建型)