设计模式 之 简单工厂模式+工厂模式

news2024/9/28 21:19:52

简单工厂模式

   创建一个工厂类,对实现了同一个接口的多个类进行实例的创建。

//抽象类 人
public abstract class HuMan
{
        public abstract void Talk();
}
//黑人实现类
public class BlackHuman : HuMan
{
    public override void Talk()
    {
        Console.WriteLine("I am BlackHuman");
    }
}
//白人实现类
public class WhiteHuman : HuMan
{
    public override void Talk()
    {
        Console.WriteLine("I am WhiteHuman");
    }
}
/// <summary>
/// 简单工厂
/// </summary>
public static class HumanFactory
{
    public static HuMan CreateHuman(HumanEnum humanEnum)
    {
        HuMan huMan = null;
        switch (humanEnum)
        {
            case HumanEnum.Black:
                huMan = new BlackHuman();
                break;
            case HumanEnum.White:
                huMan = new WhiteHuman();
                break;
            default:
                throw new NullReferenceException();
        }
        return huMan;
    }
}

//客户端调用
//创建一个白人
var whiteHuman1 =  SimpleFactory.CreateHuman(HumanEnum.White);
whiteHuman1.Talk();
//创建一个黑人
var blackHuman1 = SimpleFactory.CreateHuman(HumanEnum.Black);
blackHuman1.Talk();

复制代码

   优点:工厂中包含了必要的逻辑判断,根据客户端的选择条件动态的创建相关的类,对于客户端来说,它只需要提供创建实现类的参数,隐藏了创建实例的细节,去除了对具体实现类的依赖。

   缺点:当要新增一个实现类时,需要修改工厂类的代码(switch下增加一个Case),违背了开放-封闭原则。

当然上面的代码其实还存在很大的优化空间,我们可以先看下工厂模式的实现方案,对比下两种模式上的区别。

工厂模式

   定义一个用于创建对象的接口,让子类决定实现哪个类。工厂方法将创建对象实例的职责移交给了子类。

//定义一个创建人类的工厂接口
public interface IHumanFactory
{
    HuMan CreateHuman();
}
//定义一个创建白人的工厂
public class WhiteHumanFactory : IHumanFactory
{
    public HuMan CreateHuman()
    {
        return new WhiteHuman();
    }
}
//定义一个创建黑人的工厂
public class BlackHumanFactory : IHumanFactory
{
    public HuMan CreateHuman()
    {
        return new BlackHuman();
    }
}
//客户端调用
 var whiteHumanFactory = new WhiteHumanFactory();
var whiteHuman2 =  whiteHumanFactory .CreateHuman();
whiteHuman2.Talk();
var blackHumanFactory = new BlackHumanFactory();
var blackHuman2 = blackHumanFactory .CreateHuman();
blackHuman2.Talk();

优点:当要新增一个实现类时,只需要再增加一个实现类和创建实现类的工厂,不需要修改原有工厂的代码,保留了简单工厂对创建实例的封装,又体现了开放-封闭原则。

缺点:客户端需要决定实例化哪一个工厂来创建实现类,增加了客户端的复杂度。同时每增加一个实现类,也要增加一个工厂类,增加了代码复杂度。

简单工厂+反射

  可以通过反射技术来强化简单工厂,让简单工厂同样符合开放封闭原则。

/// <summary>
/// 简单工厂
/// </summary>
public static class HumanFactory
{
    public static HuMan CreateHuman(string humanType)
    {
         var a = Assembly.LoadFrom($"{AppDomain.CurrentDomain.BaseDirectory}DesignPatterns.Model.dll");
        return (HuMan)a.CreateInstance($"DesignPatterns.Model.Factory.{humanType}");
    }
}

客户端可以通过配置文件或者数据库中获取humanType(在程序或者数据库中维护一个参数类型+类名的字典),通过反射技术动态的创建实例。

简单工厂+依赖注入

//工厂类
public class HumanFactory
{
    private readonly Func<HumanEnum, Human> _func;
    public HumanFactory(Func<HumanEnum, Human> func)
    {
        this._func = func;
    }
    public Human  CreateHuman(HumanEnum humanEnum)
    {
        return _func(humanEnum);
    }
}

public static class HunmanDependencyInjection
{
       //维护一个实现类的字典
    private static Dictionary<HumanEnum, Type> dicHuman = new Dictionary<QRCodeType, Type>() {
        {  HumanEnum.White,typeof(WhiteHuman)},
        { HumanEnum.Black,typeof(BlackHuman)}
    };
    public static void AddHuman(this IServiceCollection serviceCollection)
    {
        serviceCollection.AddScoped<WhiteHuman>();
        serviceCollection.AddScoped<BlackHuman>();
        serviceCollection.AddScoped(factory=> {
            Func<HumanEnum, Human> func = humanType=> {
                return (Human)factory.GetService(dicHuman [humanType]);
            };
            return func;
        });
        serviceCollection.AddScoped<HumanFactory>();
    }
}
//在Startup中注入实现类和工厂
public void ConfigureServices(IServiceCollection services)
{
           services.AddHuman();
          services.AddMvc(); 
}
//客户端在构造函数中引入HumanFactory
 var  whiteHuman =  HumanFactory.CreateHuman(HumanEnum.White);
whiteHuman.Talk();

复制代码

这样我们就用Ioc实现了一个简单工厂,上面的代码示例是将实现类的字典放在工厂中维护,其实可以将字典放到配置文件或者数据库中维护,这样我们再增加新的实现类时,就不需要在修改工厂的代码,实现了实现类的动态扩展。也体现了开闭原则。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1538354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python的ITS 信息平台的设计与实现flask-django-nodejs-php

第二&#xff0c;陈列说明该系统实现所采用的架构、系统搭建采用的服务器、系统开发环境和使用的工具&#xff0c;以及系统后台采用的数据库。 最后&#xff0c;对系统进行全面测试&#xff0c;主要包括功能测试、查询性能测试、安全性能测试。 分析系统存在的不足以及将来改进…

新材料正在加速金属3D打印的应用步伐

在金属3D打印领域&#xff0c;材料性能是影响工件综合表现的关键因素&#xff0c;如强度、硬度、耐腐蚀性、抛光性能以及导热性能等&#xff0c;都与材料息息相关&#xff0c;好的材料是推动金属3D打印向更多领域应用的基础。 在这一背景下&#xff0c;上海毅速新材料推出的多款…

二十二 超级数据查看器 讲解稿 其他高级功能

二十二 超级数据查看器 讲解稿 其他高级功能 ​​点击此处 以新页面 打开B站 播放当前教学视频 点击访问app下载页面 百度手机助手 下载地址 ​ 这节课我们讲超级数据查看器高级功能2&#xff0c;讲的是设置密码以外的其他功能。 进入高级功能&#xff0c;先讲一下列表样…

【MySQL】理解关系型数据库&数据的数据模型

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

优化选址问题 | 基于节约算法求解考虑碳排放及带时间窗的物流选址问题附matlab代码

目录 问题代码问题 节约算法(Savings Algorithm)通常用于解决车辆路径问题(Vehicle Routing Problem, VRP),特别是当需要考虑如何有效地组织车辆的路线以最小化总行驶距离时。然而,当问题扩展到包括碳排放和带时间窗的物流选址问题时,算法需要相应的调整。 在这个扩展…

软考高级:软件架构评估概述和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

WM8978 —— 带扬声器驱动程序的立体声编解码器(6)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;5&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…

Java NIO和IO之间的区别

前言 NIO&#xff08;New IO&#xff09;&#xff0c;这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的&#xff0c;但实现方式不同&#xff0c;NIO主要用到的是块&#xff0c;所以NIO的效率要比IO高很多。在Java API中提供了两套NIO&#xff0c;一套是针对标准输入输出…

【Spring 事务详解】声明式事务概念

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

element-plus下拉框和输入框宽度不一致,:popper-append-to-body=“false“失效

遇到的问题&#xff1a;我修改了el-select输入框的宽度之后&#xff0c;发现下拉选项和输入框的宽度不一样了! 2. 原因控制台看到下拉项的DOM元素时插入到body里面了&#xff0c;使用:popper-append-to-body"false"发现已经废弃&#xff0c;最后发现替换成:teleporte…

Android 动态类加载实现免安装更新

随着Html5技术成熟&#xff0c;轻应用越来越受欢迎&#xff0c;特别是其更新成本低的特点。与Native App相比&#xff0c;Web App不依赖于发布下载&#xff0c;也不需要安装使用&#xff0c;兼容多平台。目前也有不少Native App使用原生嵌套WebView的方式开发。但由于Html渲染特…

宜搭低代码高级认证实操题2 faas连接器加密解密

密钥维护页-保证有一条数据 敏感信息提交页 存档页&#xff0c;只是用来存数据的审批的时候不用这个表提交数据不然会出两条 授权查看页 FaaS连接器先下载好他的示例代码然后按照要求配置好参数直接拷贝进去就行 然后需要在云开发环境里面先new一个terminal然后跑一下./builde…

全智能深度演进,一键成片让视频创作颠覆式提效

全智能一键成片&#xff0c;让内容创作的「边际成本」逼近于零。 大模型和AIGC技术的发展&#xff0c;可以用“日新月异”来形容&#xff0c;其迭代速度史无前例&#xff0c;涌现出的各类垂直应用模型&#xff0c;也使得音视频行业的应用场景更加广泛和多样化。 然而&#xff…

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework PDF: https://arxiv.org/html/2403.13248v1 1 概述 为弥补Sora不开源的缺陷&#xff0c;本文提出多代理框架Mora&#xff0c;整合先进视觉AI代理&#xff0c;复制Sora的全能视频生成能力。Mora能利用…

目标检测——PP-YOLOE-R算法解读

PP-YOLO系列&#xff0c;均是基于百度自研PaddlePaddle深度学习框架发布的算法&#xff0c;2020年基于YOLOv3改进发布PP-YOLO&#xff0c;2021年发布PP-YOLOv2和移动端检测算法PP-PicoDet&#xff0c;2022年发布PP-YOLOE和PP-YOLOE-R。由于均是一个系列&#xff0c;所以放一起解…

网络带宽 (网速) 在线测试

网络带宽 [网速] 在线测试 1. 测网速2. SPEEDTEST3. 下载、上传4. 宽带速率对照表5. 时延6. 抖动7. 丢包8. 测速节点9. 网线References 1. 测网速 https://www.speedtest.cn/ 2. SPEEDTEST https://www.speedtest.net/ ​ 3. 下载、上传 网络数据传输分为发送数据和接收数据…

Uni-app/Vue/Js本地模糊查询,匹配所有字段includes和some方法结合使用e

天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1.第一步 需要一个数组数据 {"week": "全部","hOutName": null,"weekendPrice": null,"channel": "门市价","hOutId": 98,"cTime": "…

WM8978 —— 带扬声器驱动程序的立体声编解码器(5)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;4&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…

Vue2(九):尚硅谷TodoList案例(初级版):组件化编码流程的使用

一、组件化编码流程及资料 百度网盘 请输入提取码 提取码yyds &#xff08;Vue全家桶资料&#xff09; 组件化编码流程分为三步&#xff1a; 二、实现静态组件 1、分析结构 确定组件名称&#xff08;Header,List,Item,Footer&#xff09;和个数&#xff0c;还有嵌套关系(…

InnoDB 缓存

本文主要聊InnoDB内存结构, 先来看下官网Mysql 8.0 InnoDB架构图 MySQL :: MySQL 8.0 Reference Manual :: 17.4 InnoDB Architecture 如上图所示,InnoDB内存主要包含Buffer Pool, Change Buffer, Log Buffer, Adaptive Hash Index Buffer Pool 其实 buffer pool 就是内存中的…