PHP设计模式-工厂系列(二)-工厂方法模式

        在 简单工厂模式 [ 附:PHP设计模式-简单工厂模式(静态方法工厂模式)] 中我们描述了,一个工厂的领导,让车间主管生产产品的实例。回顾一下:

class DogToy  
{  
  
}  
  
class CatToy  
{  
  
}  
  
class BearToy  
{  
  
}  
  
class FactoryManager  
{  
  
   //指定我们工厂可以生产的玩具类型  
   public static $allowToyName = array(  
       "bear", "cat", "dog"  
   );  
  
   //你让我生产什么,告诉我玩具的名字就可以了  
   public static function make($toyName)  
   {  
       //检查这种玩具是否能生产  
       $toyName = strtolower($toyName);  
       if (!in_array($toyName, self::$allowToyName)) {  
           throw new Exception("没法生产这种玩具");  
       }  
  
       //生产玩具  
       $className = ucfirst($toyName).'Toy';  
       return new $className();  
   }  
}  
  生产什么样的产品,领导只要说产品的名字,主管就会根据名字去命令车间生产相应的产品。这个主管类中的静态方法就是负责这种生产逻辑。玩具工厂运营了一年后,领导发现最近两月的订单在减少。最后经市场人员一调查。原来是公司的产品太单一了,各种玩具只有一种款式。领导觉得不行,不能这样下去了。于是命令主管,必须让车间生产多种款式的玩具。这下主管犯悉了。于是车间赶紧进行研究具有各种款式玩具的能力。研究中...

class Style1DogToy extends DogToy {

}

class Style2DogToy extends DogToy {

}

class Style1CatToy extends CatToy {

}

class Style2CatToy extends CatToy {

}

class Style3CatToy extends CatToy {

}

class Style1BearToy extends BearToy {

}

class Style2BearToy extends BearToy {
	
}
        终于研究出来了。但主管觉得,玩具的款式可能会越来越多,每个品种的玩具车间必须设立一个车间主任来管理不同款式产品的生产。所以我们设立一个车间玩具管理员的职位,并且为每个车间都任命一个车间主任,并且必须有管理产品的能力(即必须拥有make()方法)。在下面的实例中,我们建立一个抽象类,用处在于,一是可以限定每车间主任必须有make()的能力。并且,以后便于对车间主任进行统一化管理。

abstract class ToyManager {
	
	abstract function make($styleName);
}

class DogToyManager extends ToyManager {

	public function make($styleName)
	{
		//...	
	}
}

class BearToyManager extends ToyManager {
	
	public function make($styleName)
	{
		//...	
	}
}

class CatToyManager extends ToyManager {

	public function make($styleName)
	{
		//...	
	}
}
        好,各车间主任要开始干活了,他们需要根据主管的款式名称来生产相应的产品。
class DogToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'DogToy';
        return new $className();
    }              
}                  

class BearToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'BearToy';
        return new $className();
    }
}

class CatToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'CatToy';
        return new $className();
    }
}
  这时候,我们发现原来车间主管需要把自己的工作方式改变一下了。如果领导告诉他要生产什么类型的玩具,什么款式的玩具。他需要先根据类型找到相应的车间主任,再告诉主任,我们需要什么样的款式的产品就可以了。到底什么样的款式的玩具怎么做。那就是车间主任的事儿了。那我们改变一下工作方式,即改变make()方法。
class FactoryManager
{

   //指定我们工厂可以生产的玩具类型  
   public static $allowToyName = array(  
       "bear", "cat", "dog"  
   );

   //你让我生产什么,告诉我玩具的名字和款式
   public static function make($toyName, $styleName)
   {
       //检查这种玩具是否能生产  
       $toyName = strtolower($toyName);
       if (!in_array($toyName, self::$allowToyName)) {
           throw new Exception("没法生产这种玩具");
       }
                      
       //先要找到车间主任
       $managerName = $toyName."ToyManager";
       $manager = new $managerName();
       
       //告诉车间主任生产的款式是什么
       return $manager->make($styleName);
   }
}
  这时候,如果领导告知要生产一个款式1的熊玩具,只需要告诉车间主管即可,我们把所有代码全部整合到一起,如下:

class DogToy {

}

class CatToy {

}

class BearToy {

}

class Style1DogToy extends DogToy {

}

class Style2DogToy extends DogToy {

}

class Style1CatToy extends CatToy {

}

class Style2CatToy extends CatToy {

}

class Style3CatToy extends CatToy {

}

class Style1BearToy extends BearToy {

}

class Style2BearToy extends BearToy {

}

abstract class ToyManager {

    abstract public function make($styleName);
}

class DogToyManager extends ToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'DogToy';
        return new $className();
    }
}

class BearToyManager extends ToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'DogToy';
        return new $className();
    }
}

class CatToyManager extends ToyManager {

    public function make($styleName)
    {
        $className = ucfirst(strtolower($styleName)).'DogToy';
        return new $className();
    }
}

class FactoryManager
{

   //指定我们工厂可以生产的玩具类型  
   public static $allowToyName = array(
       "bear", "cat", "dog"
   );

   //你让我生产什么,告诉我玩具的名字和款式
   public static function make($toyName, $styleName)
   {
       //检查这种玩具是否能生产  
       $toyName = strtolower($toyName);
       if (!in_array($toyName, self::$allowToyName)) {
           throw new Exception("没法生产这种玩具");
       }

       //先要找到车间主任
       $managerName = $toyName."ToyManager";
       $manager = new $managerName();

       //告诉车间主任生产的款式是什么
       return $manager->make($styleName);
   }
}

$style1BearToy = FactoryManager::make('Bear', 'Style1');
var_dump($style1BearToy);

        我们看到,最近车间发生的最大变化在哪里?车间的单一款式玩具生产满足不了实际的市场需求。于是让每个车间具有多款式玩具的生产能力,设立了车间主任的职位,并为每个车间配一个车间主任。为了达到这样的需求,我们是建立了一个抽象的车间主任类(当然,也可以用接口),并且建立了三个车间主任,他们必须具备make()方法,即具有管理生产的能力。我们可以看到。实际生产产品的工作任务由原来的主管负责,被分配给了车间主任这个职位。具体实施则由各车间主任实际操作。也就是说,这些具体的实现被推向了各工厂的方法中去实现,我们把这种模式就叫就工厂方法模式。从这里我们也可以看出,工厂方法模式适用于生产同一类产品(玩具),他们都必须实现造玩具的方法。
        其实我们也可以看到,车间主管的职责,还是负责总体产品的把握,只是接受领导的命令的方式和下达命令的方式不一样了。它仍就是一个简单工厂模式。这一个业务就形成了简单工厂+工厂方法的模式了。其实很多时候,设计模式不是单一的,它可以根据业务的实际需要进行配合使用。而且个人也觉得,设计模式不可滥用,合适即可。
        说到这里,再八卦一下,前段时间看到一则关于抨击设计模式的文章。说GOF提出的设计模式理论误导了不少人,觉得没必要把设计模式总结出来,说设计系统是一种思想,设计模式只是把这些设计思想安了一个名字,没有必要,而且还误导了不少人。这种理论我同意一半,设计一个系统确实不应该照搬设计模式。但设计模式的存在价值还是很大的。首先,对于新生而言,需要一个吸取设计思想的方式,而设计模式就是思想的总结,它能帮助新手快速掌握设计的思想,至于能不能真正掌握其灵魂,就看个人的误性了。至于滥用与否,则在于人,不在于设计模式。其次,在一些系统架构的讨论会上,设计模式能帮助大家更有效地沟通,而不用一个细节一个细节去说,说过多的细节可能会适得其反,有时候甚至词不达意。所以设计模式的作用还是很大的。不应该全盘否定它。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值