经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式之工厂模式
来源:cnblogs  作者:little天  时间:2020/11/23 12:20:03  对本文有异议

关于设计模式这一块,个人觉得还是挺重要的。因为这个关乎到代码的优雅程度。

今天不讲设计模式六大原则,就单纯的来说说我对工厂模式的理解,用最通俗易懂的自然语言,讲述一下工厂模式的原理。

定义

什么是工厂模式?就是一种创建型的设计模式。这么说可能有些晦涩,用通俗易懂的话来说,就是按照一种类似于工厂生产商品的方式来对类进行实例化,而不是用到了就new一个。

简单工厂模式

现在有一个客户,肚子饿了,想吃方便面。他现在脑子里这有一个念头:快点吃到方便面,他根本就不想了解方便面到底是怎么生产出来的(客户端与实现的解耦)。这个时候如果有一个卖方便面的小店(工厂)就好了,客户只需要看一下店里有哪些方便面。然后挑选一包就好了。

优点:

白话:客户不需要知道怎么生产方便面,就可以吃到想要的方便面,甚至能挑选到自己想要的那个牌子的方便面。

书面:客户端和具体实现的解耦。

缺点:

白话:这个小店为了应对越来越多的客户需求,进货的时候进了100多种品牌的方便面,味道各不一样,描述七老比较困难。吃的方法也不一样,有一些是水煮的,有一些是干吃的,有一些是干拌的。因此老板自己也经常记错,更别说客户问的时候听得一头雾水了。客户挑了半天,可能并不能挑到自己心满意足的产品。

书面:随着数据量的增大,工厂类会变得臃肿。逻辑和实现混杂在一起,使得工厂类的内部构造变得难以理解和维护,非常不利于后期的拓展。对于客户端来说,需要知道工厂的内部实现,增加了大量的学习成本,增加了客户端的复杂度。

实现:

首先我们需要定义一个方便面的接口,每包方便面都可以吃:

  1. //noodles.php
  2. interface Noodles{
  3. public function eat();
  4. }

然后我们写两个实现类,分别代表康师傅生产的方便面,和统一生产的方便面:

  1. //kangNoodles.php
  2. class KangNoodles implements Noodles{
  3. public function eat(){
  4. echo '吃一包美味的康师傅红烧牛肉面';
  5. }
  6. }
  7. //Tongyi.php
  8. class TongyiNoodles implements Noodles{
  9. public function eat(){
  10. echo '吃一包美味的统一红烧牛肉面';
  11. }
  12. }

然后我们生成一个简单工厂:

  1. //NoodlesFactory.php
  2. class NoodlesFactory{
  3. public function createNoodles($brand){
  4. switch($brand){
  5. case 'kang':
  6. return new KangNoodles();
  7. case 'tongyi':
  8. return new TongyiNoodles();
  9. }
  10. }
  11. }

生成客户端:

  1. //SimpleFactoryDemo.php
  2. class SimpleFactoryDemo{
  3. public function setNoodles($brand){
  4. $noodles = (new NoodlesFactory())->createNoodles($brand);
  5. $noodles->eat();
  6. }
  7. }

工厂模式

还是上述场景,客户肚子饿了想吃方便面。现在我们建立一个康师傅工厂,专门生产(售卖)康师傅红烧牛肉面,再建立一个生产(售卖)统一红烧牛肉面的工厂,等等,在理想的条件下,我们甚至可以建立起100个品牌的方便面加工工厂,客户想吃哪一个牌子,直接去对应的工厂(商店)进行购买就行了。

优点:

相对于简单工厂模式,工厂模式的每一个工厂都做自己的事,避免建立起一个庞大而又臃肿的工厂。有利于代码的扩展和维护。

缺点:

每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量(个人觉得这一点可以接受,不算什么太大的缺点)

实现:

首先我们需要定义一个方便面的接口

 

  1. //noodles.php
  2. interface Noodles{
  3. public function eat();
  4. }

 

然后我们写两个实现类,分别代表生产康师傅生产的方便面,和统一生产的方便面这种商品:

  1. //kangNoodles.php
  2. class KangNoodles implements Noodles{
  3. public function eat(){
  4. echo '吃一包美味的康师傅红烧牛肉面';
  5. }
  6. }
  7. //Tongyi.php
  8. class TongyiNoodles implements Noodles{
  9. public function eat(){
  10. echo '吃一包美味的统一红烧牛肉面';
  11. }
  12. }

 

 

然后,生成一个工厂接口:

  1. //NoodlesFactory.php
  2. interface NoodlesFactory{
  3. public function createNoodles();
  4. }

我们生成两个对应的工厂:

 

  1. //KangNoodlesFactory.php
  2. class KangNoodlesFactory implements NoodlesFactory{
  3. public function createNoodles(){
  4. return new KangNoodles();
  5. }
  6. }
  7. //TongyiNoodlesFactory.php
  8. class TongyiNoodlesFactory implements NoodlesFactory{
  9. public function createNoodles(){
  10. return new TongyiNoodles();
  11. }
  12. }

 

生成客户端:

  1. //FactoryDemo.php
  2. class FactoryDemo{
  3. public function kangFunc(){
  4. $noodles = (new KangNoodlesFactory())->createNoodles();
  5. $noodles->eat();
  6. }
  7. public function TongyiFunc(){
  8. $noodles = (new TongyiNoodlesFactory())->createNoodles();
  9. $noodles->eat();
  10. }
  11. }

抽象工厂模式

还是上述场景,随着物质条件的提升,客户提出,要在吃泡面的时候加一分榨菜,形成一个套餐。这个时候怎么办?

我们可以把泡面和榨菜想象成一个“套餐”,统一交给一家工厂(商店)去帮忙搞定。市场上于是新推出一条这样的套餐:泡面——榨菜。于是各个厂家纷纷效仿,推出自家工厂的“套餐”。客户只需要到对应的工厂直接下单套餐就行了,无需其他操作。

优点:

拥有工厂模式的优点。

拥有产品族的概念,这一系列的产品源于同一厂家,易于管理约束。保证客户只使用同一家工厂的产品。

一个具体的工厂实现代表的是一个产品族,切换产品族只需要切换一下具体工厂

缺点:

如果要新增加一个产品,比如说套餐中要加入一款饮料。那么所有的工厂都要去遵循这个规定,去研发出一款自家的饮料,比较麻烦。

实现:

首先我们需要定义一个方便面的接口

  1. //noodles.php
  2. interface Noodles{
  3. public function eat();
  4. }

然后我们写两个实现类,分别代表生产康师傅生产的方便面,和统一生产的方便面这种商品:

  1. //kangNoodles.php
  2. class KangNoodles implements Noodles{
  3. public function eat(){
  4. echo '吃一包美味的康师傅红烧牛肉面';
  5. }
  6. }
  7. //Tongyi.php
  8. class TongyiNoodles implements Noodles{
  9. public function eat(){
  10. echo '吃一包美味的统一红烧牛肉面';
  11. }
  12. }

我们再写一个榨菜的接口:

  1. //Mustard.php
  2. interface Mustard{
  3. public functioneat();
  4. }

再写两个榨菜的实现类:

  1. //kangMusterd.php
  2. class kangMusterd implements Musterd{
  3. public function eat(){
  4. echo '吃一包美味的康师傅榨菜';
  5. }
  6. }
  7. //Tongyi.php
  8. class TongyiMusterd implements Musterd{
  9. public function eat(){
  10. echo '吃一包美味的统一榨菜';
  11. }
  12. }

写一个抽象工厂,包含多个产品:

  1. //AbstractFactory.php
  2. abstract AbstractFactory(){
  3. abstract public function createNoodle();
  4. abstract public function createMusterd();
  5. }

生成两个工厂类:

  1. //KangFactory.php
  2. class KangFactory extends AbstractFactory{
  3. public function createNoodles(){
  4. return new KangNoodles();
  5. }
  6. public function createMusterd(){
  7. return new KangMusterd();
  8. }
  9. }
  10. //TongyiFactory.php
  11. class TongyiFactory extends AbstractFactory{
  12. public function createNoodles(){
  13. return new TongyiNoodles();
  14. }
  15. public function createMusterd(){
  16. return new TongyiMusterd();
  17. }
  18. }

客户端:

  1. //AbstractFactoryDemo.php
  2. class AbstractFactoryDemo{
  3. public function eatKangTaocan(){
  4. $kangFactory = new KangFactory();
  5. $noodles = $kangFactory->createNoodles();
  6. $musterd = $kangFactory->createMusterd();
  7. $noodles->eat();
  8. $musterd->eat();
  9. }
  10. public function eatTongyiTaocan(){
  11. $TongyiFactory = new TongyiFactory();
  12. $noodles = $TongyiFactory->createNoodles();
  13. $musterd = $TongyiFactory->createMusterd();
  14. $noodles->eat();
  15.      $musterd->eat();
  16. }
  17. }

总结:

后两种工厂模式,其实就是把创建对象的那个行为抽象出来了,做到了低耦合。

 

原文链接:http://www.cnblogs.com/littlesky123/p/14012736.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号