【设计模式——学习笔记(下)】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),进而综合两者的内容,让知识点更加全面
目录
相关文章
|
5月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
771 157
|
5月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
621 2
|
5月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
1114 35
|
5月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
471 8
|
10月前
|
设计模式 Java 数据库连接
【设计模式】【创建型模式】工厂方法模式(Factory Methods)
一、入门 什么是工厂方法模式? 工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但由子类决定实例化哪个类。工厂方法模式使类的实例化延迟
298 16
|
10月前
|
设计模式 负载均衡 监控
并发设计模式实战系列(2):领导者/追随者模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第二章领导者/追随者(Leader/Followers)模式,废话不多说直接开始~
292 0
|
10月前
|
设计模式 监控 Java
并发设计模式实战系列(1):半同步/半异步模式
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发设计模式实战系列,第一章半同步/半异步(Half-Sync/Half-Async)模式,废话不多说直接开始~
369 0
|
10月前
|
设计模式 安全 Java
并发设计模式实战系列(12):不变模式(Immutable Object)
🌟 大家好,我是摘星!🌟今天为大家带来的是并发设计模式实战系列,第十二章,废话不多说直接开始~
244 0
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
853 11
|
10月前
|
设计模式 算法 Java
设计模式觉醒系列(04)策略模式|简单工厂模式的升级版
本文介绍了简单工厂模式与策略模式的概念及其融合实践。简单工厂模式用于对象创建,通过隐藏实现细节简化代码;策略模式关注行为封装与切换,支持动态替换算法,增强灵活性。两者结合形成“策略工厂”,既简化对象创建又保持低耦合。文章通过支付案例演示了模式的应用,并强调实际开发中应根据需求选择合适的设计模式,避免生搬硬套。最后推荐了JVM调优、并发编程等技术专题,助力开发者提升技能。