php设计模式之一工厂模式--简单工厂模式
最近在学习设计模式,很多地方还理解的不够。在这里记录一下自己学习的东西,方便自己以后查看和理解,同时也给正在学这部分的同学提供一点参考。
工厂模式的几种形态:
1、简单工厂模式(Simple Factory) |又叫做 静态工厂方法模式(Static Factory Method)
2、工厂方法模式(Factory Method) |又叫做 多态性工厂模式(Polymorphic Factory)
3、抽象工厂模式(Abstract Factory) |又叫做 工具箱模式(ToolKit)
简单工厂模式, 简单工厂模式不属于23种常用面向对象设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。其实质是由一个工厂类根据传入 的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
简单工厂模式有三个角色
1、抽象角色
2、具体角色
3、工厂角色 : 负责获取某个具体角色的实例
代码示例一
<?php /** * 一个事例 * * 一个农场,要向市场销售水果 * 农场里有三种水果 苹果、葡萄 * 我们设想:1、水果有多种属性,每个属性都有不同,但是,他们有共同的地方 | 生长、种植、收货、吃 * 2、将来有可能会增加新的水果、我们需要定义一个接口来规范他们必须实现的方法 * 3、我们需要获取某个水果的类,要从农场主那里去获取某个水果的实例,来知道如何生长、种植、收货、吃 */ /** * 虚拟产品接口类 * 定义好需要实现的方法 */ interface fruit{ /** * 生长 */ public function grow(); /** * 种植 */ public function plant(); /** * 收获 */ public function harvest(); /** * 吃 */ public function eat(); } /** * 定义具体产品类 苹果 * 首先,我们要实现所继承的接口所定义的方法 * 然后定义苹果所特有的属性,以及方法 */ class apple implements fruit{ //苹果树有年龄 private $treeAge; //苹果有颜色 private $color; public function grow(){ echo "grape grow"; } public function plant(){ echo "grape plant"; } public function harvest(){ echo "grape harvest"; } public function eat(){ echo "grape eat"; } //取苹果树的年龄 public function getTreeAge(){ return $this->treeAge; } //设置苹果树的年龄 public function setTreeAge($age){ $this->treeAge = $age; return trie; } } /** * 定义具体产品类 葡萄 * 首先,我们要实现所继承的接口所定义的方法 * 然后定义葡萄所特有的属性,以及方法 */ class grape implements fruit{ //葡萄是否有籽 private $seedLess; public function grow(){ echo "apple grow"; } public function plant(){ echo "apple plant"; } public function harvest(){ echo "apple harvest"; } public function eat(){ echo "apple eat"; } //有无籽取值 public function getSeedLess(){ return $this->seedLess; } //设置有籽无籽 public function setSeedLess($seed){ $this->seedLess = $seed; return true; } } /** *农场主类 用来获取实例化的水果 * */ class farmer{ //定义个静态工厂方法 public static function factory($fruitName){ switch ($fruitName) { case 'apple': return new apple(); break; case 'grape': return new grape(); break; default: throw new badFruitException("Error no the fruit", 1); break; } } } class badFruitException extends Exception{ public $msg; public $errType; public function __construct($msg = '' , $errType = 1){ $this->msg = $msg; $this->errType = $errType; } } /** * 获取水果实例化的方法 */ try{ $appleInstance = farmer::factory('apple'); var_dump($appleInstance); }catch(badFruitException $err){ echo $err->msg . "_______" . $err->errType; }
代码示例二
<?php //简单工厂方法 interface Math { public function calculation( $x, $y ); } //加法实现 class Sum implements Math { public function calculation( $x, $y ) { return $x + $y; } } //减法实现 class Sub implements Math { public function calculation( $x, $y ) { return $x - $y; } } //工厂方法 class Factory { public static function doMath( $type ) { switch( $type ) { case "+": return new Sum(); break; case "-": return new Sub(); break; } } } $obj = Factory::doMath('-'); echo $obj->calculation( 1, 2 );
一个工厂类Factory,根据访问传入的符号不同,去动态的实例化不同的类。这样我们就不需要自己去实例化类,无论用户要进行何种计算,只需要实例化时:Factory::doMath('-'),传入自己想要的计算符号即可。而不需要自己去实例化相应的计算类。并且
调用统一的计算方法calculation(1, 2),传入参数即可获得结果。这样看来,简单工厂方法确实很是方便。但是,简单工厂方法违背了设计模式的一个原则:开放与封闭原则
什么是开放与封闭原则呢?简单的讲就是:程序对扩展来说是开放的,对修改来说是封闭的。本案例,如果我想加入一个乘法计算,那么很简单我再添加一个乘法的类,但是,我必须去修改Factory类的doMath方法,将我新加入的乘法计算添加进去,这样就破坏了原来的类,也就违背了封闭原则。这时,工厂方法就解决了简单工厂违背开放与封闭原则的问题
浙公网安备 33010602011771号