设计模式(二)-创建者模式(3)-抽象工厂模式

news2024/11/25 22:56:54

一、为什么需要抽象工厂模式?

在工厂模式中,我们需要定义多个继承于共同工厂抽象基类的工厂子类,这些子类负责创建一个对应的对象。工厂模式存在一个缺点就是:每次扩展新的工厂子类,就会增加系统的复杂度。

如果我们知道把所有产品(比如车)分为几个产品族(比如自行车族、汽车族),那么工厂子类就对应指定的产品族进行“批量”创建对象。若有新的产品,则工厂子类创建该新产品对象。(工厂子类内部逻辑,类似于简单工厂模式)

抽象工厂模式 ,类似于简单工厂模式和工厂模式混合运用而成的模式。(参考上篇文章“工厂模式”的最后一个代码例子)

优点: 不需要每次定义一个新的产品类时,就要扩展新的工厂子类。工厂子类提供一个产品族中多个对象的创建工作,客户端可以方便使用某个产品族中的对象。

缺点: 产品族扩展难。要增加一个新系列的某一产品,要定义产品抽象类、产品实现类,工厂抽象基类,工厂子类。

【角色】
某系列抽象基类: 用以定义某产品族的特征和行为的抽象接口。
某系列的某产品实现类: 继承某系列抽象基类,用以实现某系列里某产品的特征和行为的具体类。
工厂抽象基类: 用以定义创建对象的特征的抽象接口。特征行为包括提供某系列产品的抽象方法。
工厂子类: 对对应的实现类进行实例化。实现提供某系列某产品的方法。

请添加图片描述

二、例子

需求: 假定某些地方的主要交通工具有自行车和汽车。为了满足人们交通便利的需求,现有XX公司和YY公司这两家公司,对市场推行了两种运营模式:租车和共享车。也就是说,租车和共享车是这两家公司所推广的两个产品系列业务,即两个产品族。

1)定义产品族和具体产品


//共享车系列(产品族)
    public abstract class Share
    {
        public abstract void Move();
    }
    
//租借车系列
    public abstract class Rent
    {
        public abstract void Move();
    }

//XX公司-共享-自行车
    public class XXBikeShare : Share
    {
        public override void Move(){
            Console.WriteLine("Share XXBike move.");
        }
    }
    
//XX公司-共享-汽车
    public class XXCarShare : Share
    {
        public override void Move(){
            Console.WriteLine("share XXCar move.");
        }
    }
    
//XX公司-租借-自行车
    public class XXBikeRent : Rent
    {
        public override void Move(){
            Console.WriteLine("Rent XXBike move.");
        }
    }

//XX公司-租借-汽车
    public class XXCarRent : Rent
    {
        public override void Move(){
            Console.WriteLine("Rent XXCar move.");
        }
    }

//YY公司-共享-自行车
    public class YYBikeShare : Share
    {
        public override void Move() {
            Console.WriteLine("share YYBike move.");
        }
    }

//YY公司-共享-汽车
    public class YYCarShare : Share
    {
        public override void Move() {
            Console.WriteLine("share YYCar move.");
        }
    }

//YY公司-租借-自行车
    public class YYBikeRent : Rent
    {
        public override void Move(){
            Console.WriteLine("Rent YYBike move.");
        }
    }

//YY公司-租借-汽车
    public class YYCarRent : Rent
    {
        public override void Move(){
            Console.WriteLine("Rent YYCar move.");
        }
    }

2)定义工厂基类和工厂子类


//定义提供两个产品族的抽象方法
    public abstract class Factory
    {
        public abstract Share ProvideS(string args);
        public abstract Rent ProvideR(string args);
    }

//XX公司落实产品业务:租借和共享
    public class XXFactory : Factory
    {
        public override Share ProvideS(string args)
    {
            Share share = null;
            switch (args)
            {
                case "XXBike":
                    share = new XXBikeShare(); break;
                case "XXCar":
                    share = new XXCarShare(); break;
                default:
                    throw new ArgumentException("args is Invalid. new obj failed.");
            }

            return share;
        }

        public override Rent ProvideR(string args)
        {
            Rent rent = null;
            switch (args)
            {
                case "XXBike":
                    rent = new XXCarRent(); break;
                case "XXCar":
                    rent = new XXBikeRent(); break;
                default:
                    throw new ArgumentException("args is Invalid. new obj failed.");
            }

            return rent;
        }
    }
    
//YY公司落实产品业务:租借和共享
    public class YYFactory : Factory
    {
        public override Share ProvideS(string args)
        {
            Share share = null;
            switch (args)
            {
                case "YYBike":
                    share = new YYBikeShare(); break;
                case "YYCar":
                    share = new YYCarShare(); break;
                default:
                    throw new ArgumentException("args is Invalid. new obj failed.");
            }

            return share;
        }

        public override Rent ProvideR(string args)
        {
            Rent rent = null;
            switch (args)
            {
                case "YYBike":
                    rent = new YYBikeRent(); break;
                case "YYCar":
                    rent = new YYCarRent(); break;
                default:
                    throw new ArgumentException("args is Invalid. new obj failed.");
            }

            return rent;
        }
    }

3)在客户端使用


class Program
    {
        static void Main(string[] args)
        {
            Factory xx = new XXFactory();
            Factory yy = new YYFactory();

            var sharexxCar = xx.ProvideS("XXCar");
            sharexxCar.Move();

            var rentyyBike = yy.ProvideR("YYBike");
            rentyyBike.Move();

            Console.ReadLine();
        }
    }

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

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

相关文章

探索SPI:深入理解原理、源码与应用场景

文章目录 一、初步认识1、概念2、工作原理3、作用场景 二、源码分析1、ServiceLoader结构2、相关字段3、核心方法 三、案例connector连接器小案例1、新建SPI项目2、创建扩展实现项目1-MongoDB3、创建扩展实现项目2-Oracle4、测试 Spring应用1、创建study工程2、创建forlan-test…

如何远程控制别人电脑进行技术支持?

怎么提供远程技术支持? “我朋友的电脑出了一些问题,问我是否可以远程控制他的电脑帮他解决。请问有什么办法能快速的远程控制别人的电脑进行故障排除呢?” 当电脑出问题时,多数情况下会采用电话沟通进行解决&#…

Modbus转Profinet网关在金银精炼控制系统中应用案例

金银精炼控制系统中采用Modbus转Profinet网关(XD-MDPN100)连接1200plc与PID控制阀门进行通讯,通过控制PID阀门的大小来实现温度的恒温控制。这一系统的好处在于它能够提高金银精炼过程的效率和精确度。PID控制阀门可以根据温度的变化实时调整…

【Linux】vscode远程连接ubuntu,含失败解决方案

删除vscode远程连接 打开‪C:\Users\GIGA\.ssh\config文件,GIGA是windows下自己的用户名。 删除‪C:\Users\GIGA\.ssh\config文件里的所有内容,点击保存;然后刷新。 可以看出SSH 远程连接已经被删除了。 vscode远程连接ubuntu 在弹出的…

计算机毕业设计选题推荐-个人博客微信小程序/安卓APP-项目实战

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

DolphinDB 基于 Glibc 升级的性能优化实战案例

在高并发查询、查询需要涉及很多个分区的情况下,低版本的 glibc(低于2.23)会严重影响查询性能。需要升级 glibc 解决该问题优化性能。我们撰写了本文,通过 patchelf 工具修改可执行文件和动态库的 rpath,达到无需升级系…

SaleSmartly新增AI意图识别触发器!让客户享受更精准的自动化服务

AI意图识别技术是对话式AI中很重要的组成部分,通俗点来说就是一种可以识别用户在对话中表达的意图的技术。通过对大量数据的分析和学习,AI可以理解用户想要获得的信息,并根据这些信息来采取相应的行动或提供相应的响应。而在对话式AI中&#…

GPT-4充当“规划师、审计师”,颠覆性双层文生图表模型

DALL-E 3、Midjourney、Stable Diffusion等模型展现出了强大的创造能力,通过文本便能生成素描、朋克、3D、二次元等多种类型的高质量图片,但在生成科学图表(柱状、直方、箱线、树状等)方面却略显不足。 这是因为模型在生成图表时…

你学了Python之后让你成为行业卷王,升职加薪更有优势

都说Python能够实现自动化,那么Python具体能应用在哪些地方?哪些岗位学了Python更有优势?今天我们来看看一些大神将Python应用的出神入化的成果。 在这之前,先跟为大家分享个真实的故事。我朋友小宇前段时间为了一个品牌设计的大项目,想方案…

SSL证书对网站SEO的好处

随着网络安全意识的提高,越来越多的网站开始采用SSL证书来保护自己的数据传输过程。那么,SSL证书真的能为网站SEO带来好处吗?下面将为您分析这个问题。 加强用户体验和信任度 SSL证书不仅能确保数据传输的安全性,还能让客户感受…

【技术指南资料】编码器与正交译码器

我想提出一个关于PicoScope7新的译码器功能讨论。它已经推出一段时间,但你可能不知道这在汽车领域是扮演相当重要的角色。 正交译码器被用在转子位置传感器来转换关于旋转轴角度及方向的信息。 举例来说,它在电机上采用一对二进制的信号型式。 这种传感器…

Linux 时区设置

对于服务器来说,linux的时区影响着运行之上的数据库和后端程序的时区 应该和数据库和后端及其他程序的时区保持一致 其他相关时区的设置 pgsql时区设置: php时区设置: 1.显示当前的时间和时区 date结果类似下面,图中显示的是ut…

【揭秘】MySQL逻辑架构:一文带你全面了解!

mysql是我们开发过程中使用的最多的数据库,大多数程序员平时都是做CRUD,如果CRUD慢了,那就再加一个索引,如果加上索引还不行,那基本上开发就没辙了,因为对mysql内部理解不深入、不清晰,所以问题…

智能货柜:无人零售行业的新宠

智能货柜:无人零售行业的新宠 与早期的传统自动售货机相比,智能货柜的投放场景正呈现多样化的趋势。除了人流密集的公共场所,一些办公室、健身房等室内场景也成为商家争相争夺的热门位置。 其次,在无人零售行业中,许多…

转录组学习第三弹-下载SRR数据并转成fastq

下载数据 前面已经安装好了需要的软件,那么我们现在需要下载我们练习需要用到的sra数据。从 SRA 数据库下载数据有多种方法。可以用ascp快速的来下载 sra 文件,也可以用wget或curl等传统命令从 FTP 服务器上下载 sra 文件。另外sra-tools的prefetch也支…

Zeet构建多云战略充分发挥云的优势

大型企业通常拥有基础设施和应用团队,有能力围绕自己的业务需求构建所需平台。但对于技术团队精简、预算紧张的小企业来说,定制平台往往不现实而且难以扩展,是负担不起的“奢侈品”。 这一情况催生了平台即服务(PaaS)…

ospf路由选路及路由汇总

一、知识补充 1、ABR和ASBR 1.1 ABR ABR指的是边界路由,通常位于两个或多个区域之间,用于在不同的OSPF区域之间传递信息。当一个路由器同时连接到两个或多个区域时,它就成为了ABR,它需要维护每个区域的拓扑信息和路由表&#x…

PC3392H高性价方案比10V-120V输入1.5A大电输出内置MOS管带EN功能实现零功耗使能只需极少元器件

1.PC3392H 特性  通过使能脚关断实现零功耗  宽电压输入范围 10V 至 120V  最大输出电流 1.5A  集成功率 MOS 管  外围器件少  输出短路保护  温度保护  逐周期限流  输出电压灵活可靠  ESOP8 2. 描述 PC3392H 一款宽电压范围降压型 DC-DC 电源…

CentOS安装nodejs

查看可安装的版本 dnf module list nodejs选择需要版本安装 dnf module install nodejs:<stream>查看版本

使用JDK自带java.util.logging.Logger引起的冲突问题

现象&#xff1a; 应用代码如下&#xff1a; import javax.script.ScriptEngineManager;ScriptEngineManager manager new ScriptEngineManager(); manager.getEngineByName("JavaScript"); 在TongWeb8上运行出错&#xff0c;日志如下&#xff1a; Servlet.servi…