工厂模式
工厂模式是封装对象的创建,用于解耦对象的创建和使用。工厂模式的实现分为三种:简单工厂、工厂方法和抽象工厂。
在《设计模式》一书中,简单工厂模式被看作是工厂方法模式的一种特例,所以工厂模式只被分为工厂方法和抽象工厂两类,都属于创建型模式。
简单工厂:是将不同的创建逻辑放到一个工厂类中,使用 if-else 或 map 的实现方式由工厂类根据参数判断返回要实例化的类。
//被创建的对象
interface IWork {
public function perform() ;
}
class Shopping implements IWork {
public function perform() {
echo 'Shopping~~~ ' ;
}
}
class Meal implements IWork {
public function perform() {
echo 'Meal~~~' ;
}
}
class Cleaning implements IWork {
public function perform() {
echo 'Cleaning~~~' ;
}
}
//使用简单工厂的方式去获取创建对象
class WorkFactory {
public static function createObj($type) {
if ($type == 'shopping') {
return new Shopping() ;
} elseif ($type == 'Meal' ) {
return new Meal() ;
} elseif ($type == 'Cleaning' ) {
return new Cleaning() ;
}
}
}
//使用工厂类创建对象
$object = WorkFactory::createObj('shopping') ;
$object->perform() ;
$object = WorkFactory::createObj('Cleaning') ;
$object->perform() ;
工厂方法:是将不同创建逻辑放到不同工厂类中,这样需要新增实现的时候,增加一个类即可。工厂方法模式比简单工厂模式更加符合开闭原则。
在实现中,可以先用一个工厂类的工厂(if-else / map 逻辑这个类中)来得到对应的工厂类,再用这个工厂类来创建对象。
//被创建的对象
interface IWork {
public function perform() ;
}
class Shopping implements IWork {
public function perform() {
echo 'Shopping~~~ ' ;
}
}
class Meal implements IWork {
public function perform() {
echo 'Meal~~~' ;
}
}
class Cleaning implements IWork {
public function perform() {
echo 'Cleaning~~~' ;
}
}
//工厂类,将对象的创建放到不同的工厂类中
interface IFactory {
public function createObj() ;
}
class ShoopingFactory implements IFactory {
public function createObj() {
return new Shopping() ;
}
}
class MealFactory implements IFactory {
public function createObj() {
return new Meal() ;
}
}
class CleaningFactory implements IFactory {
public function createObj() {
return new Cleaning() ;
}
}
//工厂类的工厂
class WorkFactory {
public static function createObj($type) {
if ($type == 'shopping') {
$factory = new ShoopingFactory() ;
} elseif ($type == 'Meal' ) {
$factory = new MealFactory() ;
} elseif ($type == 'Cleaning' ) {
$factory = CleaningFactory() ;
}
return $factory->createObj() ;
}
}
//使用工厂类的工厂创建对象
$demo = WorkFactory::createObj('shopping');
$demo->perform() ;
$demo = WorkFactory::createObj('Meal');
$demo->perform() ;
什么时候使用简单工厂,什么时候使用工厂方法模式?
将部分代码块剥离封装为独立的函数或者类,是为了剥离后代码更加清晰,更加可读和可维护,所以如果代码块本身不复杂,就没有必要去剥离封装。
基于这个思想,当每个对象的创建逻辑都比较简单的时候,推荐使用简单工厂模式,将多个对象的创建逻辑放到一个工厂类中。
当对象的创建逻辑比较复杂,需要组合其他对象或者有各种初始化操作的时候,为了避免设计一个过于庞大的简单工厂类,推荐使用工厂方法,将复杂的创建逻辑拆分到各自的工厂类中。
抽象工厂:提供一个接口,用于创建多个相关或依赖的对象,让一个工厂负责创建多个不同类型的对象。可以有效的减少工厂类的个数。
抽象工厂模式的缺点在于创建对象类的扩展,假如在需要加入新的创建对象类,那么几乎所有的工厂类都需要进行修改。
//被创建的对象(一组)
interface IWork {
public function perform() ;
}
class Shopping implements IWork {
public function perform() {
echo 'Shopping~~~ ' ;
}
}
class Meal implements IWork {
public function perform() {
echo 'Meal~~~' ;
}
}
class Cleaning implements IWork {
public function perform() {
echo 'Cleaning~~~' ;
}
}
//被创建的对象(二组)
interface IPay {
public function spending() ;
}
class ShoppingPay implements IPay {
public function spending() {
echo 'ShoppingPay~~~ ' ;
}
}
class MealPay implements IPay {
public function spending() {
echo 'MealPay~~~' ;
}
}
class CleaningPay implements IPay {
public function spending() {
echo 'CleaningPay~~~' ;
}
}
//创建抽象类用来获取工厂类
abstract class AbstractFactory {
public abstract function createWorkObj() ;
public abstract function createPayObj() ;
}
class ShoopingFactory extends AbstractFactory {
public function createWorkObj() {
return new Shopping() ;
}
public function createPayObj() {
return new ShoppingPay() ;
}
}
class MealFactory extends AbstractFactory {
public function createWorkObj() {
return new Meal() ;
}
public function createPayObj() {
return new MealPay() ;
}
}
class CleaningFactory extends AbstractFactory {
public function createWorkObj() {
return new Cleaning() ;
}
public function createPayObj() {
return new CleaningPay() ;
}
}
//工厂类的工厂
class Factory {
public static function loadFactory($type,$fType='work') {
if ($type == 'Shopping') {
$factory = new ShoopingFactory() ;
} elseif ($type == 'Meal' ) {
$factory = new MealFactory() ;
} elseif ($type == 'Cleaning' ) {
$factory = new CleaningFactory() ;
}
//也可以根据需要继续拆分为不同的工厂类
if ($fType == 'work') {
return $factory->createWorkObj() ;
} else {
return $factory->createPayObj() ;
}
}
}
$object = Factory::loadFactory('Shopping') ;
$object->perform() ;
$object = Factory::loadFactory('Shopping','pay') ;
$object->spending() ;
学习过程中,觉得看起来很懵或者感觉看懂了又没太看懂的时候,代码敲一遍,大概就明白了~~~ 反正我是这样的~~
网友评论