设计模式 一 简单工厂Simple Factory(工厂模式)

<?php
/**
 * 简单工厂的演变
 */

 /**
  * 引导
  *
  * 1、当看到 “new”, 就会想到具体。导致代码更脆弱更缺乏弹性。,使用接口让代码具有弹性。
  * 2、针对接口编程,可以隔离掉以后系统可能发生的一大堆改变。why?如果代码是针对接口而写,那么通过多态,它可以与任何新类实现该接口。
  * 但是,当代码使用大量的具体类时,等于是自找麻烦,因为一旦加入新的具体类,就必须改变代码。也就是说,你的代码并非“对修改关闭”。想用新的具体类型来扩展代码,必须重新打开它。
  * 3、从封装特性,中寻找线索,找出会变化的方面,把它们从不变的部分分离出来。
 */


/**
 * 
 * 1、识别变化
 */

class PizzaStore {

	public function orderPizza() {			
		//为了让系统有弹性,我们很希望这是一个抽象类或接口。
		$pizza = new Pizza(); //变化部分

		$pizza->prepare(); //准备
		$pizza->bake(); //烘烤
		$pizza->cut(); //切片
		$pizza->box(); //包装
		return $pizza;
	}
}

/**
 * 当需要更多Pizza 类型时。。。
 * 必须添加一些代码,来“决定” 适合的比萨类型,然后再“制作”这个比萨。
 */

class PizzaStore {

	public function orderPizza($type) {
		
		if ("cheese" == $type) {//奶酪比萨
			$pizza = new CheesePizza(); 		
		} elseif ("greek" == $type) {//希腊比萨
			$pizza = new GreekPizza();		
		} elseif ("pepperoni" == $type) {//香肠比萨
			$pizza = new PepperoniPizza();		
		} else {
			//
		}

		$pizza->prepare();
		$pizza->bake();
		$pizza->cut();
		$pizza->box();
		return $pizza;
	}
}

/**
 * 明显可见,如果实例化“某些”具体类,将使orderPizza() 出现问题,而且也无法对orderPizza“修改关闭”。
 * 但是,现在我们已经知道哪些会改变,哪些不会改变,该是使用封装的时候了。
 */



/**
 * 封装创建对象的代码,创建比萨的代码转移到另一个对象中,由这个对象专职创建比萨。
 * 该对象称为“工厂”。
 */

class SimpleFactory {
	
	public function createPizza($type) {
		if ("cheese" == $type) {//奶酪比萨
			$pizza = new CheesePizza(); 		
		} elseif ("greek" == $type) {//希腊比萨
			$pizza = new GreekPizza();		
		} elseif ("pepperoni" == $type) {//香肠比萨
			$pizza = new PepperoniPizza();		
		} else {
			//
		}
		return $pizza;
	}
}

abstract class Pizza {
	public $name;
	public $price;
	abstract public function perpare();
	abstract public function bake();
	abstract public function cut();
	abstract public function box();
}

class CheesePizza extends Pizza {
	public $name;
	public $price;
	public function __construct() {
		$this->name = '奶酪比萨';
		$this->price = '10';
	}
	public function perpare() {

	}
	
	public function bake() {
		//TODO
	}
	
	public function cut() {
		//TODO
	}
	
	public function box() {
		//TODO
	}
	
	public function getName() {
		return $this->name;
	}
	//其他行为操作省略
}

class GreekPizza extends Pizza {
	public $name;
	public $price;
	public function __construct() {
		$this->name = '希腊比萨';
		$this->price = '5';
	}
	
	public function perpare() {
		//TODO
	}
	
	public function bake() {
		//TODO
	}
	
	public function cut() {
		//TODO
	}
	
	public function box() {
		//TODO
	}

	public function getName() {
		return $this->name;
	}
	//其他行为操作省略
}


/**
 * 问:我曾经看过一个类似的设计方式,把工厂定义成一个静态的方法。这有何差别?
 * 答:利用静态方法定义一个简单的工厂,这是个常见的技巧,常被成为“静态工厂”。为何使用静态方法?因为不需要使用创建对象来实例化对象。
 * 但请记住,这也有缺点,不能通过继承来改变创建方法的行为。
 */

 /**
  * 接下,重写PizzaStore 类.
  * 我们所要做的是仰仗工厂来为我们创建比萨。
  */
class PizzaStore {
	public $factory;
	public function __construct(SimpleFactory $simpleFactory ) {
		$this->factory = $simpleFactory;
	}
	
	public function orderPizza($type) {		
		//为了让系统有弹性,我们很希望这是一个抽象类或接口。
		$pizza = $this->factory->createPizza($type); //变化部分
		
		$pizza->perpare(); //准备
		$pizza->bake(); //烘烤
		$pizza->cut(); //切片
		$pizza->box(); //包装
		return $pizza;
	}
}

$simpleFactory = new simpleFactory();
$pizzaStore = new PizzaStore($simpleFactory);
$pizza = $pizzaStore->orderPizza('cheese');
echo $pizza->name.":".$pizza->price;

/**
 * 我们知道对象组合可以再运行时动态改变行为,因为我们可以更换不同的实现。在PizzaStore例子中要如何做到这点呢?有哪些工厂的实现能够被我们自由地更换?
 */


 /**
  * 总结:
  * 
  * 简单工厂(simple factory)
  * 1、simple factory 模式的工厂类根据提供给他的参数,返回几个可能产品类中的一个类的实例。通常它的返回的类都有一个公共的父类和公共的方法。
  * 2、simple factory 模式实际上不是gof 23个设计模式中的一员,反而比较像是一种编程习惯,但由于经常被使用,给他一个”荣誉奖“。不要因为不是设计模式而忽略它的用法。
  *
  * 具体结构如下:
  * -工厂类角色creator(SimpleFactory):工厂类在客户端直接控制下(create 方法)创建产品对象。
  * -抽象产品角色product(pizza):定义简单工厂创建对象的父类或者它们的共同拥有的接口。可以使抽象类也可以是接口。
  * -具体产品角色ConcreteProduct(CheesePizza) : 定义工厂创建的具体对象。
  * -客户端client(PizzaStore):工厂客户,通过客户端方法调用工厂创建实例。
  */




更多精彩 在 工厂方法


设计模式目录
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值