设计模式之工厂

什么是工厂模式?

将对象的创建与使用分开,也就是不自己创建对象了,有一个统一的地方创建对象,我们直接用就行,这么说可能有些抽象,不过没关系,接着往下看吧。

简单工厂模式

定义: 创建一个工厂干所有活。

        例如这里有一个car接口,对应三个品牌奥迪(AUdi)、宝马(BMW)、奔驰(Benz)实现类。我们的目标就是要调用Audi、BMW、Benz类里面的方法,看看下面如何实现的。

360e11e6c3d043258f33befa41cbb18e.png

car接口

5872522c69a044f0baf906cebf7fc806.png

每个实现类里面都输出自己的汽车类型 ,这里只贴BMW,Audi和Benz是一样的。

      9055bbbf4b0242ba9ef455bc2942ae98.png

现在我们定义一个工厂,统一管理三个品牌车的实例创建。

a3e8b234ad1943798e2e3e54670fb102.png

测试类,实现上述说的调用Audi、BMW、Benz类里面的方法,传哪辆车,工厂就帮我们创建哪辆车的实例对象,我们就能直接调用里面的方法。看到这,你大概对工厂模式有了解了吧,其实就是找了个代理人(工厂),他帮你干脏活。

f39b838efa0147928e5ce1942a075b52.png

但是简单工厂模式存在很明显的缺陷: 维护成本太高了,如果有新的品牌车来,我们要在工厂代码里面直接去进行修改,这违反了开闭原则,以后代码复杂后,改代码原有的很有可能造出新bug,并且原有代码长了后也不好维护。

优点:逻辑简单。封装了创建逻辑,将创建和使用解耦
 

工厂模式

        简单工厂模式的升级版,改进工厂,我们原来简单工厂模式创建工厂就是一个对象囊括所有的工作,现在是定义一个接口,也就是定义一套规则,具体实现可以根据实际需求增加,我知道你觉得这很抽象,还是接着往下看例子。

        现在的工厂是一个工厂接口,而汽车作为实现类,上述的缺点我们说过,后续添加新品牌车非常不方便,而这里直接实现CarFactory就行,还是不懂的话接着看代码。

        cde577cf8c4845c08a79a587aa917e9d.png

代码:

        这是汽车接口。

8443e02c2ca14690a01d0186bf9eb6fa.png

宝马的实现类。

abc870582f0a498c8f2f44c553c96cec.png

        现在我们想要宝马就可以直接调用宝马工厂的buildACar方法,同理想生产奔驰就用奔驰工厂调用该方法。如果新品牌车来了,例如小米汽车,创建一个小米类实现工厂接口,生产小米汽车就直接调用小米工厂调用buildACar方法。

        看到这里,是不是明白许多了?  我们通过定义一个工厂接口,实现多个工厂类来

解决拓展困难的问题,现在拓展新品牌汽车无需修改原有代码,而是新增代码,维护性与拓展性大大提升。

552988bbe5b8407bbe64541b9061a62e.png

你以为这个就没有缺点了吗? 当我们同一个工厂要生产不同品质的车该如何解决呢?例如宝马车分为A级别、B级别,这又得改原有代码。

优点:相比简单工厂,利于扩展和维护。比如当新增一种车时,只需要对应创建具体产品类和负责生产新品种车的具体工厂即可。符合“开闭原则”,便于扩展。
缺点:具有一定的局限性,只能生产出一种产品(由接口内部方法决定),比如我要生成BMW牌子的某级别车就不直接支持。
 

抽象工厂模式

定义:主要用于解决“一类产品”的创建问题,比如各种牌子的B级车,C级车。可以从自底向上抽象归纳的角度考虑。底层有多种抽象后可以归为一类的东西,这里就是B级车,C级车。也可以是篮球,足球,然后工厂需要负责创建不同牌子的篮球,足球。也可以理解为抽象工的工厂接口比工厂方法的更多,功能更强大。

区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
 

        现在的要求是我要创建不同品牌的汽车,例如奥迪、奔驰,又要创建同一品牌不同级别的车,例如奔驰的A级别、B级别,要满足上述说的好维护、解耦、好拓展要求。

         大家现在看下图,只需要关注我红框内三个部分,只看这三个部分是不是和上面一模一样? C代表C级车,上面工厂模式也把他当作C级车就是一模一样的。但是现在我设计他的时候加入了B级车接口方法,那么我的奔驰实现类就要重写B级车和C级车方法。往下看测试方法。

76e2a49a0cc048d09d95c795c874d71c.png

 代码:

这是抽象汽车工厂,里面两个接口代表创建b级车和c级车。

e702288319934d37a15574c7419da24c.png

 

宝马车实现这个接口,现在宝马车也能生产b级车和c级车了

2fba09a4baa84134b7ffb32b4d99a92a.png

return返回的你可能不太明白,BMW3和BMW5是两个级别的车,级别也有接口和实现类,为了约束生产车的级别。这里如果不明白可以去听听接口是用来干嘛的,如果能理解其实就是一句话,用来指定规则,约束生成的对象,这里就是为了约束b级工厂只能生产b级车。

903b02e059834e76b395737f99ebea61.png

这是某个具体实现类里面的方法,例如BMW3,这个就不是很重要了,随便看一眼,主要是看懂上面的接口和实现类。

309763ae638547a5bad627bea0278968.png

测试类,我们现在既可以添加新品牌车,又能创建不同级别的车。

0bd441476dd74fcc8d7aa9de91580a3b.png

但是还是存在一些缺点:这里等级只有b和c,要拓展新的等级非常麻烦。

优点:

1. 解耦,例如classA想调用classB,A不需要管B的实例化或者说不感知B如何实例化,B的实例化交给工厂类。

 

2. 代码复用,如果创建对象B需要一定代码量,但是很多地方都要用到B,那么B就要创建很多次重复代码,而工厂模式对B进行了封装,我们只需要在工厂类里面统一管理。既做到了代码重复利用,也做到了以后的可维护与修改。

3.符合迪米特法则和单一职责法则,使用者只需要如何使用就行,无需去感知创建实例逻辑。

一. 什么是迪米特法则

迪米特法则(Law of Demeter )又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能少的了解。不和陌生人说话。英文简写为: LoD。

迪米特法则的目的在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。

二. 什么是单一职责原则#

  一个类只做它该做的事情。

  单一职责原则的核心就是高内聚,即一个 模块只完成一项功能。单一职责,顾名思义就是一个类只有一个职责,只做一件事情。我们在大学里学的软件工程和软件项目管理中,老师都在强调软件设计要追求“高内聚、低耦合”,以提高模块的重用性和移植性,而单一职责原则就很好的说明了高内聚。

总结来说

4d81346265e649c5aff5dcc588bf5b6a.png

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.ccc.。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值