C# 设计模式(1)——简单工厂模式、工厂模式、抽象工厂模式
1、前言
上一篇写了设计模式原则有助于我们开发程序的时候能写出高质量的代码(牵一发而不动全身),这个系列还是做个笔记温习一下各种设计模式,下面就看看简单工厂模式、工厂模式、抽象工厂模式。
2、简单工厂模式
其实我们可以这么理解简单工厂模式,就是专门负责生产对象的一个类,作用就是创建具体产品的实例。我们平时创建创建一个对象的时候通常都是new出来的,此时这个类就依赖与这个对象,说白了就是耦合度过高啦。需求变化的时候我们不得不去修改此类的源码。这时候就要用面向对象(OO)的思想去处理这个问题。把变化大的类封装起来,实现就不去动它。下面看个栗子,就生产、制造不同的汽车分析简单工厂模式的作用。
/// <summary>
/// 车 抽象类
/// </summary>
public abstract class Car
{
/// <summary>
/// 制造车--抽象方法
/// </summary>
public abstract void Make();
/// <summary>
/// 卖车--抽象方法
/// </summary>
public abstract void Sale();
} /// <summary>
/// 奥迪车
/// </summary>
public class ADCar : Car
{
public override void Make()
{
Console.WriteLine("制造了一辆奥迪车");
} public override void Sale()
{
Console.WriteLine("销售了一辆奥迪车");
}
}
/// <summary>
/// 奔驰车
/// </summary>
public class BCCar : Car
{
public override void Make()
{
Console.WriteLine("制造了一辆奔驰车");
} public override void Sale()
{
Console.WriteLine("销售了一辆奔驰车");
}
}
看客户端的调用
Car c = new ADCar();
c.Make();
c.Sale();
Console.WriteLine("\n");
Car b = new BCCar();
b.Make();
b.Sale();
我们可以看都是通过new一个ADCar 来创建一个实例, 想要奔驰的一样的要new一个出来 我想要n个那不是炸锅了。所以这里就创建一个车的简单工厂类。让这个工厂类来创建Car实例。这里的switch是C#的语法糖,感觉是不是有点香。
/// <summary>
/// 车的工厂类
/// </summary>
public class CarFactory
{
public static Car OpCar(string carName)
{
Car? car = null;
var ret = carName switch
{
"AD" => car=new ADCar(),
"BC" => car=new BCCar(),
_ => car=new ADCar()
};
return ret;
} } //客户端调用
Car cc = CarFactory.OpCar("AD");
cc.Make();
cc.Sale(); Car cc1 = CarFactory.OpCar("BC");
cc1.Make();
cc1.Sale();
这时候是不是就可以了,解决了客户端太过于依赖具体对象的问题,别急如果我再来一个宝马 就要还添加一个继承Car的BMCar 还要在 CarFactory的OpCar里面再加一个判断。按照开闭原则来说添加类没有啥影响,但是修改了CarFactory里面OpCar的代码就不符合开闭原则了。下面的工厂模式就专门解决这个问题。
3、工厂模式
在简单工厂模式中系统难以扩展且违背了开闭原则,这样使得简单工厂的实现逻辑过于复杂。工厂模式就是把具体创建类的实例中放在子工厂类中,工厂类不再负责所有产品的创建工厂类只提供创建实例。还是看上面的栗子我们加一个抽象工厂类出来,让不同的品牌去继承
/// <summary>
/// 车工厂类
/// </summary>
public abstract class CarFactory1
{
/// <summary>
/// 抽象方法
/// </summary>
public abstract Car OpCar();
}
/// <summary>
/// 奥迪工厂
/// </summary>
public class ADCarFactory1 : CarFactory1
{
public override Car OpCar()
{
return new ADCar();//在具体的工厂中实例化产品
}
}
/// <summary>
/// 奔驰工厂
/// </summary>
public class BCCarFactory1 : CarFactory1
{
public override Car OpCar()
{
return new BCCar();//在具体的工厂中实例化产品
}
} //客户端调用
CarFactory1 cf = new ADCarFactory1();
Car car = cf.OpCar();
car.Make();
car.Sale(); CarFactory1 cf2 = new BCCarFactory1();
Car car2 = cf2.OpCar();
car2.Make();
car2.Sale();
效果跟上面一样的,这里是不是就实现了新增一个宝马的话不用修改Factory里面的代码了只要在创建一个BMCarFactory1跟BMCar就可以了。我们要获取一个产品的时候我们就获取一个具体的工厂来实例它。 它是不是解决了简单工厂的不足也符合了开闭原则。问题也来了如果我不单单要销售车、卖车 搞大了我还要卖飞机卖火箭咋搞。这种不可能再去创建无数个工厂嘛。来看看抽象工厂模式。
4、抽象工厂模式
工厂模式它功能单一点只针对一个品牌,解决不了一系列的问题,卖火箭、卖飞机等等这些不同的品牌。如果我们在设计程序中显然工厂模式已经满足不了我们的需求了。抽象工厂模式就能很好的解决这个问题。这里我们还是新增一个抽象类,他提供制造、销售汽车的同事也提供制造销售飞机。实现方法只要实现自己品牌的的产品就可以了。
/// <summary>
/// 产品抽象类
/// </summary>
public abstract class PcFactory
{
/// <summary>
/// 车
/// </summary>
/// <returns></returns>
public abstract Car OpCar();
/// <summary>
/// 飞机
/// </summary>
/// <returns></returns>
public abstract Plan OpPlan();
}
/// <summary>
/// 奥迪pc工厂
/// </summary>
public class ADPcFactory : PcFactory
{
public override Car OpCar()
{
return new ADCar();
} public override Plan OpPlan()
{
return new ADPlan();
}
}
/// <summary>
/// 奔驰pc工厂
/// </summary>
public class BCPcFactory : PcFactory
{
public override Car OpCar()
{
return new BCCar();
} public override Plan OpPlan()
{
return new BCPlan();
}
} //客户端调用
PcFactory pf = new ADPcFactory();
Car adc = pf.OpCar();
Plan adc2 = pf.OpPlan();
adc.Make();
adc.Sale(); adc2.Make();
adc2.Sale(); PcFactory pf2 = new BCPcFactory();
Car abc = pf2.OpCar();
Plan abc2 = pf2.OpPlan();
abc.Make();
abc.Sale(); abc2.Make();
abc2.Sale();
我们可以看出抽象工厂跟工厂的区别就在于它能生产多种产品(车、飞机)工厂只能是单一的产品(车)。抽象类只注重创建的多个产品,不会关心具体的实现是什么。实现又是不通的产品工厂实现的。这样的话客户端也从具体的产品中解耦出来。
5、总结
简单工厂模式
优点:降低刻度段与具体产品的耦合度,实现new让工厂类去完成,也提高了代码的复用率。
缺点:违反了开闭原则系统扩展困难,而且工厂类集中了所有的业务逻辑一旦出问题整个系统都要受牵连。
工厂模式
优点:符合开闭原则新增功能不会区修改以前的代码。
缺点:产品功能单一写车的功能只能弄车,而不能加飞机、火箭的操作。
抽象工厂模式
优点:降低系统耦合度利于维护扩展,对于加系列产品符合开闭原则;
缺点:对于功能添加又不符合开闭原则了。看着是不是跟优点有冲突。这样说吧我现在要加一个宝马类不用修改业务逻辑添加一个BMCarFactory1跟BMCar就可以了。这是系列问题。如果我要加一个销毁的方法(之前就定义了制作、销售)那是不是还要在抽象类Car、Plan里面加一个抽象方法 继承里面的通通都要实现它。所以程序设计之初没有考虑到后面一个一个的改很麻烦。
一个系统要求不被所有客户端依赖到具体的实现这是所有工厂模式的应用的前提,这就要具体问题具体分析了。不可能说我要打印一个Holl Word还来搞设计模式嘛,高射炮打蚊子没有必要。各种模式都有好有坏,相对论就是这么说的,你得到一些的时候必然会失去一些,快乐要有悲伤作伴,雨过自然天晴吗。加了设计模式以后代码量肯定要上去的带给我们方便的同时也会增加风险。以前不解为啥要创建那么多项目,文件夹,现在想想就那么回事了。
PS:流年似水,岁月如歌,承受委屈是一种胸怀,接受误解是一种心怀,这个世界上失去什么东西都不可怕,惟一可怕的是失去你的心,失去你的勇气,只要你坚韧不拔地奋斗,只要你眼睛看向未来,生命就永远属于你,生命的辉煌也一定永远属于你。
C# 设计模式(1)——简单工厂模式、工厂模式、抽象工厂模式的更多相关文章
- java之设计模式工厂三兄弟之抽象工厂模式
[学习难度:★★★★☆,使用频率:★★★★★] 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工 ...
- 设计模式(一): abstract factory抽象工厂模式 -- 创建型模式
1.定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 2.适用场景 1.一个系统要独立于它的产品创建.组合和表示. 2.一个系统要由多个产品系列中的一个来配置. 3.当你要 ...
- 设计模式C++学习笔记之七(AbstractFactory抽象工厂模式)
抽象工厂,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.对于工厂方法来说,抽象工厂可实现一系列产品的生产,抽象工厂更注重产品的组合. 看代码: 7.1.解释 main(),女 ...
- php设计模式课程---3、为什么会有抽象工厂方法
php设计模式课程---3.为什么会有抽象工厂方法 一.总结 一句话总结: 解决简单工厂方法增加新选择时无法满足面向对象编程中的开闭原则问题 1.什么是面向对象编程中的开闭原则? 应该对类的增加开放, ...
- 【设计模式】 模式PK:抽象工厂模式VS建造者模式
1.概述 抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可.而建造者模式则是要求按 ...
- Android设计模式(十二)--抽象工厂模式
问题: 抽象工厂模式,是一个,狠恶心的模式,那么这个模式在Android有没实用到过呢? 1.定义: 抽象工厂模式:为创建一组相关或者是相互依赖的对象提供一个接口,而不须要指定他们的详细类. 2.使用 ...
- 系统架构-设计模式(适配器、观察者、代理、抽象工厂等)及架构模式(C/S、B/S、分布式、SOA、SaaS)(干货)
博客园首页是需要分享干货的地方,今天早上写的<HRMS(人力资源管理系统)-从单机应用到SaaS应用-系统介绍>内容下架了,所以我就按照相关规定,只分享干货,我把之前写完的内容整理发布上来 ...
- 简单理解C#中的抽象工厂模式是什么概念!
抽象工厂模式向客户端提供一个接口,使得客户端在不必指定具体类型的情况下,创建多个产品族中的对象.本文采取的仍然是接着以前的那个快餐店的例子.现在,快餐店经常良好,逐渐发展壮大,为了适合不同地方人的饮食 ...
- 【编程思想】【设计模式】【创建模式creational】抽象工厂模式abstract_factory
Python版 https://github.com/faif/python-patterns/blob/master/creational/abstract_factory.py #!/usr/bi ...
- 对象创建型模式------Abstract Factory(抽象工厂)
1. 意图 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.2. 别名 Kit3. 动机 假设我们要开发一款游戏,当然为了吸引更多的人玩,游戏难度不能太大 ...
随机推荐
- [源码解析] PyTorch 如何实现后向传播 (4)---- 具体算法
[源码解析] PyTorch 如何实现后向传播 (4)---- 具体算法 目录 [源码解析] PyTorch 如何实现后向传播 (4)---- 具体算法 0x00 摘要 0x01 工作线程主体 1.1 ...
- DH密钥交换
DH密钥交换 密模运算 所谓幂模,就是先做一次幂运算,再做一次模运算. 模运算有以下性质: 也就是说,先模再乘和先乘再模,只要最后都模了同一个模数,结果都是一样. 有了这个性质,我们首先得到幂模运算的 ...
- wpa_supplicant启动出错rfkill: Cannot open RFKILL control device
在板子是调试网络,千辛万苦把wpa_supplicant及其依赖都移植编译进来了,在板子上调试启动的时候启动报错了 D/wpa_supplicant( 1152): wpa_supplicant v2 ...
- Python hashlib Unicode-objects must be encoded before hashing
Python2中没有这个问题 python3中 hashlib.md5(data)函数中data 参数的类型应该是bytes hash前必须把数据转换成bytes类型 Python 2.7.12 (d ...
- Python pip 和pip3区别 联系
python 有python2和python3的区别 那么pip也有pip和pip3的区别 大概是这样的 pip是python的包管理工具,pip和pip3版本不同,都位于Scripts\目录下: 如 ...
- Github图床设置
创建新仓库 点击右上角加号->新建仓库,填写基本信息后点击下面的创建即可 https://github.com/new 创建新令牌 点击设置->开发者设置->私人令牌->生成新 ...
- jvm优化理解
jvm架构理解 jvm程序执行流程 编译器和解释器协调工作流程 在部分商用虚拟机中(如HotSpot),java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或者某段代码执行的特别频繁后就会 ...
- silky微服务业务主机简介
目录 主机的概念 通用主机 web主机 业务主机类型 使用web主机构建微服务应用 使用通用主机构建微服务应用 构建具有websocket能力的微服务应用 构建网关 开源地址 在线文档 主机的概念 s ...
- mui中openWindow方法的通用封装
因为做项目跳转新页面和传参的场景太多了,而且有的页面需要的跳转动画也不一样,每次都写一大堆openWindow方法的配置项太麻烦,因此自己简单封装了一个小函数,用来方便webview页面的跳转和传参. ...
- 跟着老猫来搞GO-容器(1)
前期回顾 前面的一章主要和大家分享了GO语言的函数的定义,以及GO语言中的指针的简单用法,那么本章,老猫就和大家一起来学习一下GO语言中的容器. 数组 数组的定义 说到容器,大家有编程经验的肯定第一个 ...