<?php

	/**
	 * 1.2 工厂方法模式
	 * 解决的问题:
	 * 	如何解决多个类实例化对象的问题。
	 * 	
	 * 解决的方案:
	 * 	定义一个用于创建对象的接口,让子类决定
	 * 	实例化哪一个类。工厂方法使一个类的实例
	 * 	化延迟到其子类。
	 * 
	 * 该模式包含四种角色:
	 * 	1. 抽象产品角色(一个)
	 * 		职责:它是具体工厂角色所创建的对象
	 * 			  的父类。负责描述所有实例所共
	 * 			  有的公共接口。
	 * 	2. 具体产品角色
	 * 		职责:它是具体工厂角色所要创建的目
	 * 			  标。
	 * 	3. 抽象工厂角色
	 * 		职责:负责描述所有具体工厂所共有的
	 * 			  公共接口。
	 * 	4. 具体工厂角色
	 * 		职责:具体实现产品实例化的场所。
	 * 		
	 * 优点:
	 * 		1. 与简单工厂模式相同
	 * 		2. 当添加新运算时,就不需要修改工厂
	 * 		   中的代码了,这就遵循了开闭原则,
	 * 		   
	 * 缺点:
	 * 		1. 同简单工厂模式
	 * 		
	 * 使用场景:
	 * 		1. 当一个类不知道它所必须创建的对象
	 * 		   的类的时候。
	 * 		2. 当一个类希望由它的子类来指定它所
	 * 		   创建的对象的时候。
	 * 		3. 当类将创建对象的职责委托给多个帮
	 * 		   助子类中的某一个,并且你希望将哪
	 * 		   一个帮助子类是代理者这一信息局部
	 * 		   化的时候。
	 */

	//抽象产品角色
	abstract class Operation {
		
		public static $numA;
		public static $numB;

		abstract protected function getResult();

	}


	//具体产品角色
	/**
	* 加法子类
	*/
	class Add extends Operation {
		public function getResult(){
			// return parent::$numA + $this->numB;
			return parent::$numA + parent::$numB;
		}
	}
	/**
	* 减法子类
	*/
	class Minus extends Operation {
		public function getResult(){
			return parent::$numA - parent::$numB;
		}
	}

	/**
	* 乘法子类
	*/
	class Mul extends Operation {
		public function getResult(){
			return parent::$numA * parent::$numB;
		}
	}

	/**
	* 除法子类
	*/
	class Div extends Operation {
		public function getResult(){
			if(parent::$numB != 0){
				return parent::$numA / parent::$numB;
			}
		}
	}


	//工厂角色
	// 定义一个类专门用于实例化加减乘除四个类
	interface OperFactry{
		public function createObj();
	}

	//具体工厂角色
	class AddFactry implements OperFactry{
		public function createObj(){
			return new Add();
		}
	}

	class MinusFactry implements OperFactry{
		public function createObj(){
			return new Minus();
		}
	}
	class MulFactry implements OperFactry{
		public function createObj(){
			return new Mul();
		}
	}
	class DivFactry implements OperFactry{
		public function createObj(){
			return new Div();
		}
	}


//客户端

Operation::$numA=3;
Operation::$numB=3;
$factry=new AddFactry(); //此时若要更改为其他运
						 //算直接改此处即可
$obj=$factry->createObj();
echo $obj->getResult();


?>