C# 设计模式——简单工厂模式、工厂模式、抽象工厂模式
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:流年似水,岁月如歌,承受委屈是一种胸怀,接受误解是一种心怀,这个世界上失去什么东西都不可怕,惟一可怕的是失去你的心,失去你的勇气,只要你坚韧不拔地奋斗,只要你眼睛看向未来,生命就永远属于你,生命的辉煌也一定永远属于你。
版权声明:本文为 魏杨杨 原创文章并发布到博客园, 除了【萬仟网】外, 其他平台欢迎转载,但必须在文章页面明显位置写明作者和出处,非常感谢。技术交流QQ群 99210270
微信扫一扫关注我公众号
一起学习,一起进步