主頁 > 軟體設計 > 設計模式-工廠方法

設計模式-工廠方法

2023-04-30 07:56:17 軟體設計

工廠方法模式

簡單工廠的不足

上節的簡單工廠,需要拓展時比如修改工廠類,違背了設計模式的開閉原則
簡單工廠類直接生成各個子類產品,而工廠方法則有一個抽象工廠類,宣告了創建產品的工廠方法,而各個不同的子類產品交由各個不同的具體工廠去完成創建,拓展時,只需要新建一個具體工廠即可,具有更好的靈活性和拓展性

在工廠方法模式中,存在4個角色:

  • 抽象產品
  • 具體產品
  • 抽象工廠
    宣告了創建產品的抽象方法,回傳抽象產品,由具體工廠去實作創建具體產品的方法
  • 具體工廠
    實作創建產品的抽象方法,創建并回傳某一種具體產品

工廠方法模式下的多日志工廠

Log(抽象產品)

抽象Log宣告了一個記錄日志的方法

package com.example.fxfactory.model;

import java.io.IOException;

public abstract class Log {

    public abstract void doLog() throws IOException;
}

ConsoleLog(具體產品)

Log的具體類,控制臺日志,它將doLog重寫為在控制臺列印日志資訊

package com.example.fxfactory.model;

import java.text.SimpleDateFormat;
import java.util.Date;

public class ConsoleLog extends Log{
    @Override
    public void doLog() {
        Date date = new Date();
        SimpleDateFormat pattern = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String str = pattern.format(date) + "  console log";
        System.out.println(str);
    }
}

FileLog(具體產品)

Log的另一個具體類,檔案日志,它將doLog重寫為記錄日志到filelog.txt檔案中去

package com.example.fxfactory.model;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileLog extends Log {
    @Override
    public void doLog() throws IOException {
        File dir = new File("./log");
        if (!dir.exists()) {
            dir.mkdirs();
        }

        File checkFile = new File("./log","filelog.txt");
        FileWriter writer = null;
        try {
            if (!checkFile.exists()) {
                checkFile.createNewFile();
            }
            writer = new FileWriter(checkFile, true);
            Date date = new Date();
            SimpleDateFormat pattern = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String str = pattern.format(date) + "  file log";

            writer.append(str);
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != writer)
                writer.close();
        }
    }
}

LogFactory(抽象工廠)

抽象的日志工廠,宣告了一個創建日志的方法,回傳型別為抽象的日志

package com.example.fxfactory.factory;

import com.example.fxfactory.model.Log;

public abstract class LogFactory {

    public abstract Log createLog();
}

ConsoleLogFactory(具體工廠)

控制臺日志工廠,重寫創建日志方法,回傳一個控制臺日志實體

package com.example.fxfactory.factory;

import com.example.fxfactory.model.ConsoleLog;
import com.example.fxfactory.model.Log;

public class ConsoleLogFactory extends LogFactory {
    @Override
    public Log createLog() {
        return new ConsoleLog();
    }
}

FileLogFactory(具體工廠)

檔案日志工廠,重寫創建日志方法,回傳一個檔案日志實體

package com.example.fxfactory.factory;

import com.example.fxfactory.model.FileLog;
import com.example.fxfactory.model.Log;

public class FileLogFactory extends LogFactory {
    @Override
    public Log createLog() {
        return new FileLog();
    }
}

測驗

Main.java

package com.example.fxfactory;

import com.example.fxfactory.factory.ConsoleLogFactory;
import com.example.fxfactory.factory.FileLogFactory;
import com.example.fxfactory.factory.LogFactory;
import com.example.fxfactory.model.Log;

import java.io.IOException;

public class Main {

    public static void main(String[] args) throws IOException {
        LogFactory logFactory = new ConsoleLogFactory();
        Log consoleLog = logFactory.createLog();
        consoleLog.doLog();

        logFactory = new FileLogFactory();
        Log fileLog = logFactory.createLog();
        fileLog.doLog();
    }
}

看起來,我們似乎并不需要LogFactory,直接創建2個不同的具體Factory不也行嗎?那我們嘗試換一種寫法:

空工廠

抽象工廠換為一個空工廠,createLog方法回傳null,新增一個切換到具體工廠的方法,接收具體工廠名,將自己變為指定的具體工廠

package com.example.fxfactory.factory;

import com.example.fxfactory.model.Log;

public class LogFactory {

    public LogFactory siwtch(String logType){
        switch (logType){
            case "console":{
                return new ConsoleLogFactory();
            }
            case "file":{
                return new FileLogFactory();
            }
            default:{
                return this;
            }
        }
    }

    public Log createLog(){
        return null;
    }
}

測驗

Main.java

LogFactory logFactory = new LogFactory();
        logFactory = logFactory.siwtch("console");
        Log consoleLog = logFactory.createLog();
        consoleLog.doLog();

        logFactory = logFactory.siwtch("file");
        Log fileLog = logFactory.createLog();
        fileLog.doLog();

現在我們不需要知道具體工廠類了,只需要知道用于指定它們的名字就行,不過要拓展新的具體工廠,還需要維護空工廠的switch方法

總結

工廠方法的優點

★ 客戶無須關心生成細節和具體產品的類名
★ 良好的多型性:創建細節完全封裝在具體工廠內
易拓展性:無須修改抽象工廠,新增基于抽象工廠的新具體工廠類即可

工廠方法的缺點

★ 新產品和新具體工廠成對,一定程度上增加了系統復雜性
★ 雙重抽象(產品和工廠),一定程度上增加了系統的抽象性和理解難度

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/551522.html

標籤:設計模式

上一篇:大流量時代,如何規劃系統流量提升可靠性

下一篇:返回列表

標籤雲
其他(158343) Python(38110) JavaScript(25398) Java(18011) C(15221) 區塊鏈(8261) C#(7972) AI(7469) 爪哇(7425) MySQL(7152) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5870) 数组(5741) R(5409) Linux(5334) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4565) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1964) Web開發(1951) HtmlCss(1929) python-3.x(1918) 弹簧靴(1913) C++(1912) xml(1889) PostgreSQL(1874) .NETCore(1857) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 設計模式-工廠方法

    工廠方法模式 簡單工廠的不足 上節的簡單工廠,需要拓展時比如修改工廠類,違背了設計模式的開閉原則 簡單工廠類直接生成各個子類產品,而工廠方法則有一個抽象工廠類,宣告了創建產品的工廠方法,而各個不同的子類產品交由各個不同的具體工廠去完成創建,拓展時,只需要新建一個具體工廠即可,具有更好的靈活性和拓展性 ......

    uj5u.com 2023-04-30 07:56:17 more
  • 大流量時代,如何規劃系統流量提升可靠性

    摘要:本文主要是對《鳳凰架構》的解讀,講述規劃系統流量的幾種方式。 本文分享自華為云社區《大流量時代,如何規劃系統流量提升可靠性》,作者:breakDawn 。 透明多級分流系統 對系統流量進行規劃, 要注意以下2個原則 盡可能減少單點部件, 或者減少到達單點部件的流量或者作用 奧卡姆剃刀原則,確定 ......

    uj5u.com 2023-04-28 17:54:52 more
  • 淺談復雜業務系統的架構設計

    復雜系統的架構設計不是一蹴而就的,合適的才是正確的。希望本文能夠對您在進行復雜系統設計時有一定的參考意義。 ......

    uj5u.com 2023-04-28 17:53:37 more
  • 大流量時代,如何規劃系統流量提升可靠性

    摘要:本文主要是對《鳳凰架構》的解讀,講述規劃系統流量的幾種方式。 本文分享自華為云社區《大流量時代,如何規劃系統流量提升可靠性》,作者:breakDawn 。 透明多級分流系統 對系統流量進行規劃, 要注意以下2個原則 盡可能減少單點部件, 或者減少到達單點部件的流量或者作用 奧卡姆剃刀原則,確定 ......

    uj5u.com 2023-04-28 17:51:22 more
  • 淺談復雜業務系統的架構設計

    復雜系統的架構設計不是一蹴而就的,合適的才是正確的。希望本文能夠對您在進行復雜系統設計時有一定的參考意義。 ......

    uj5u.com 2023-04-28 17:50:27 more
  • 【單例設計模式原理詳解】Java/JS/Go/Python/TS不同語言實作

    簡介 單例模式(Singleton Pattern)屬于創建型設計模式,這種模式只創建一個單一的類,保證一個類只有一個實體,并提供一個訪問該實體的全域節點。 當您想控制實體數目,節省系統資源,并不想混用的時候,可以使用單例模式。單例有很多種實作方式,主要分為懶漢和餓漢模式,同時要通過加鎖來避免執行緒安 ......

    uj5u.com 2023-04-27 10:46:01 more
  • 【單例設計模式原理詳解】Java/JS/Go/Python/TS不同語言實作

    簡介 單例模式(Singleton Pattern)屬于創建型設計模式,這種模式只創建一個單一的類,保證一個類只有一個實體,并提供一個訪問該實體的全域節點。 當您想控制實體數目,節省系統資源,并不想混用的時候,可以使用單例模式。單例有很多種實作方式,主要分為懶漢和餓漢模式,同時要通過加鎖來避免執行緒安 ......

    uj5u.com 2023-04-27 10:32:38 more
  • 系統認知篇:防腐層、門面模式及適配模式的本質

    門面模式和配接器模式是代碼級的設計模式,而防腐層本質是一種防御型策略,在更高的層級對系統進行解耦。通常情況下,防腐層包含一系列的門面類和配接器類以及一些轉換器類。 ......

    uj5u.com 2023-04-27 08:47:06 more
  • 系統認知篇:防腐層、門面模式及適配模式的本質

    門面模式和配接器模式是代碼級的設計模式,而防腐層本質是一種防御型策略,在更高的層級對系統進行解耦。通常情況下,防腐層包含一系列的門面類和配接器類以及一些轉換器類。 ......

    uj5u.com 2023-04-27 08:46:30 more
  • 5 種微服務網關介紹

    微服務網關作為微服務后端服務的統一入口,它可以統籌管理后端服務,主要分為資料平面和控制平面:

    資料平面主要功能是接入用戶的HTTP請求和微服務被拆分后的聚合。使用微服務網關統一對外暴露后端服務的API和契約,路由和過濾功能正是網關的核心能力模塊。另外,微服務網關可以實作攔截機制和專注跨橫切面的功能... ......

    uj5u.com 2023-04-26 09:34:17 more