普通工厂模式
首先我们创建继承于animal的猫狗类,使用普通工厂模式,通过制定传入值的不同,确定调用那种具体实现类。
<?php
//抽象类
abstract class animal{
public abstract function eat();
}
//具体实现类
class cat extends animal{
public function eat()
{
echo 'cat eats fish<br>';
}
}
class dog extends animal{
public function eat(){
echo 'dog eats meat';
}
}
读取输入值如果是cat调用cat的eat方法,dog则调用dog的eat方法,其他返回空。
<?php
require_once 'animal.php';
class factory{
public function eat($type){
switch($type){
case 'cat':
$cat = new cat();
return $cat->eat();
case 'dog':
$dog = new dog();
return $dog->eat();
default:
return null;
}
}
}
//测试
$factory = new factory();
$factory->eat('dog');
这种方法直观易懂,但依赖于输入值,当程序简单时,并没有什么问题。假设我的程序很复杂,包含很多实现类名称,如果每次调用都要将类名称一字不差的输入,难度较大。这时可以将调用方法放到工厂类中,通过实例化工厂的方式调用相应的方法。
工厂方法
与普通工厂通过传入值不同的方法进行实例化的方式不同,工厂方法将不同类的实例化写成相应的方法,通过实例化工厂调用不同工厂方法的方式,调用不同的类。
<?php
require_once 'animal.php';
class factory{
//猫的工厂方法
public function catFactory(){
$cat = new cat();
return $cat->eat();
}
//狗的工厂方法
public function dogFactory(){
$dog = new dog();
return $dog->eat();
}
}
//测试
$factory = new factory();
$factory->dogFactory();
每次调用都需要实例化工厂方法有点复杂,我们可以把工厂类中的方法改为static,无需实现即可调用。
#静态工厂方法
将工厂方法中的方法改为static,调用时不实例化工厂,直接调用。
class factory{
public static function catFactory(){
$cat = new cat();
return $cat->eat();
}
public static function dogFactory(){
$dog = new dog();
return $dog->eat();
}
}
//测试
factory::catFactory();
我们避免了因为拼写错误而调用错误的类,但是,如果需求更改,要求增加一个duck类呢,于是我们创建继承animal的duck类
class duck extends animal{
public function eat(){
echo 'duck eats beans';
}
}
接着我们在工厂方法类中增加duck的实现方法
<?php
require_once 'animal.php';
class factory{
.......
//duck 工厂方法
public static function duckFactory(){
$duck = new duck();
return $duck->eat();
}
}
如果我们要添加chicken,penguin,pig,bear,bird等等的类呢?每次都需要修改factory工厂,这似乎违反了开闭原则。
开闭原则:对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。
抽象工厂
提供一个创建一系列或相互依赖对象的接口,而无需指定它们具体的类。
<?php
require_once 'animal.php';
//抽象工厂
abstract class abstractfactory{
abstract function eat($type);
}
//具体工厂实现
class catFactory extends abstractfactory{
public function eat(){
$cat = new cat();
return $cat->eat();
}
}
class dogFactory extends abstractfactory{
public function eat(){
$dog = new dog();
return $dog->eat();
}
}
//测试
$factory = new dogFactory();
$factory->eat();
一般每个工厂实现类只需要一个实例,在这个例子中,catFactory和dogFactory都只需要一个实例,因此最好将这种类实现为一个单例类Singleton。