当前位置: 首页 >  网技达人 >  设计模式-工厂方法

设计模式-工厂方法

导读:工厂方法模式.简单工厂的不足.上节的简单工厂,需要拓展时比如修改工厂类,违背了设计模式的开闭原则.简单工厂类直接生成各个子类产品,而工厂方法则有一个抽象工厂类,声明了创建产品的工厂方法,而各个不同的子类产品交由各个不同的具体工厂去完成创建,拓展时,只需要新建一个具体工厂即可,具有

工厂方法模式

简单工厂的不足

上节的简单工厂,需要拓展时比如修改工厂类,违背了设计模式的开闭原则
简单工厂类直接生成各个子类产品,而工厂方法则有一个抽象工厂类,声明了创建产品的工厂方法,而各个不同的子类产品交由各个不同的具体工厂去完成创建,拓展时,只需要新建一个具体工厂即可,具有更好的灵活性和拓展性

在工厂方法模式中,存在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方法

总结

工厂方法的优点

★ 客户无须关心生成细节和具体产品的类名
★ 良好的多态性 :创建细节完全封装在具体工厂内
易拓展性 :无须修改抽象工厂,新增基于抽象工厂的新具体工厂类即可

工厂方法的缺点

★ 新产品和新具体工厂成对,一定程度上增加了系统复杂性
★ 双重抽象(产品和工厂),一定程度上增加了系统的抽象性和理解难度

内容
  • 修复 GitLab 的 CI Runner 提示找不到 pwsh 执行文件
    修复 GitLab 的 CI R
    2023-12-11
    本文告诉大家如何修复使用 GitLab 的 Runner 做 CI 时提示 “pwsh”: executable fil
  • RocketMQ消费者是如何负载均衡的
    RocketMQ消费者是如何负载
    2023-12-09
    摘要:RocketMQ 支持两种消息模式:集群消费( Clustering )和广播消费( Broadcasting )
  • 翻越相机标定的奥林匹斯
    翻越相机标定的奥林匹斯
    2023-12-07
    在机器视觉领域,相机标定是不可或缺的一步,而张氏标定法,因其灵活性,是各种标定方法中最有影响力的一种,称其为相机标定的
  • 解析关于Tomcat Servlet-request的获取请求参数及几种常用方法
    解析关于Tomcat Servl
    2023-12-06
    摘要: 本文主要讲解Tomcat之Servlet-request请求参数、Servlet转发机制、常用方法.本文分享自华
  • 零信任介绍
    零信任介绍
    2023-12-04
    什么是零信任?.答:.零信任是一种条件访问控制模型,需要持续进行信任验证,然后才允许对应用和数据进行最低权限访问。零信任
  • 在光线追踪中避免自相交的方法
    在光线追踪中避免自相交的方法
    2023-12-04
    这是我阅读 Ray Tracing Gem 的一篇笔记,《避免自相交的快速可靠的方法》是 Ray Tracing Gem
  • FlashDuty Changelog 2023-09-07 | 新增深色模式与主题配置
    FlashDuty Change
    2023-12-04
    FlashDuty:一站式告警响应平台,前往此地址免费体验!.FlashDuty.现在已经全面支持了深色模式,这为您提供
  • 女童裤子
    女童裤子
    2024-01-10
    女童裤子.产品介绍.我们的女童裤子是为年龄在3-12岁之间的女孩设计的。我们的裤子不仅样式多样,而且舒适耐穿,适合学校、
  • 儿童运动服
    儿童运动服
    2023-12-16
    儿童运动服.产品功能.我们的儿童运动服采用高品质的面料和工艺制作而成,具有出色的透气性和舒适性,可以让孩子在运动中保持干
  • 裙子
    裙子
    2023-12-16
    裙子.产品描述.我们的裙子采用高品质的面料制成,款式多样,适合各种场合穿着。无论是休闲的街头漫步,还是正式的商务会议,我
  • 短裤
    短裤
    2023-12-11
    时尚舒适,尽显运动魅力——短裤.产品功能.透气吸汗:采用透气材质制作,有效吸收汗液,让您在运动中保持干爽舒适。.伸缩自如
  • 风衣
    风衣
    2023-12-21
    风衣.产品功能.透气性高,能够有效排出体内热量和汗液,保持身体舒适.防风防水,能够有效阻挡外界风雨,保护身体不受天气影响
  • 儿童外套
    儿童外套
    2023-12-06
    儿童外套.产品功能.我们的儿童外套具有多种功能,包括保暖、防风、防水和舒适。它们采用高质量的面料制成,能够有效地抵御寒冷
  • 外套
    外套
    2023-12-06
    外套.外套是一种经典的服装单品,不仅给人温暖的保护,还可以提升整体的时尚感。我们的外套采用高品质的材料和工艺**而成,既
  • 儿童T恤
    儿童T恤
    2023-12-26
    儿童T恤.儿童T恤是一种专门为儿童设计的上衣,具有舒适、时尚、环保等特点,是孩子们*常穿着的必备单品。.产品功能.儿童T
  • 衬衫
    衬衫
    2023-12-31
    产品介绍:衬衫.产品功能.衬衫是一种适合各种场合穿着的服装,既可以正式地穿在工作场所,也可以搭配牛仔裤穿在休闲场合。.衬
  • 休闲鞋
    休闲鞋
    2024-01-05
    休闲鞋 - 轻松舒适的时尚选择.产品功能.休闲鞋 是一款适合各种活动的多功能鞋,其设计灵感来源于慢生活和自由精神。采用轻