随着编程项目经验的增加,从服务于业务逻辑到针对项目的全局设计。认识到设计模式在开发过程中 \的重要性,遵循 s.o.l.i.d 五大基准原则。它拓展了我的视野,让代码更加灵活,看起来更加富有美感.\美是构建万物的哲学思想.
我们学习的设计模式分为三类:创建者模式、结构型模式、行为型模式;创建型模式与对象的创建有关;结构型模式处理类或对象的组合;而行为型模式是对类或对象怎样交互和怎样分配职责进行描述;
内容:本文介绍的是 php 设计模式的创建型一篇。包括:单例模式(singleton), 多例模式(multiton), 工厂方法模式(factory method), 抽象工厂模式(abstract factory), 简单工厂模式(simple factory), 原型模式(prototype), 对象池模式(pool), 建造者模式(builder)
推荐:《php教程》
(一)单例模式(singleton)
● 定义
保证一个类只有一个实例,并且提供一个访问它的全局访问点。系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
● 代码示例
class singleton{ /** * @var singleton */ private static $instance; /** * 不允许从外部调用以防止创建多个实例 * 要使用单例,必须通过 singleton::getinstance() 方法获取实例 */ private function __construct() { } /** * 通过懒加载获得实例(在第一次使用的时候创建) */ public static function getinstance(): singleton { if (null === static::$instance) { static::$instance = new static(); } return static::$instance; } /** * 防止实例被克隆(这会创建实例的副本) */ private function __clone() { } /** * 防止反序列化(这将创建它的副本) */ private function __wakeup() { }}
(二)多例模式(multiton)
● 定义
在多例模式中,多例类可以有多个实例,而且多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。1. 通过实例容器保存容器。2. 利用私有构造阻止外部构造。3. 提供getinstantce()方法获取实例.
● 代码示例 两个对象通过一个类进行多次实例化
abstract class multiton { private static $instances = array(); public static function getinstance() { $key = get_called_class() . serialize(func_get_args()); if (!isset(self::$instances[$key])) { $rc = new reflectionclass(get_called_class()); self::$instances[$key] = $rc->newinstanceargs(func_get_args()); } return self::$instances[$key]; } /** * 该私有对象阻止实例被克隆 */ private function __clone() { } /** * 该私有方法阻止实例被序列化 */ private function __wakeup() { }} class hello extends multiton { public function __construct($string = 'world') { echo "hello $string\n"; } } class goodbye extends multiton { public function __construct($string = 'my', $string2 = 'darling') { echo "goodbye $string $string2\n"; }}$a = hello::getinstance('world'); $b = hello::getinstance('bob'); // $a !== $b $c = hello::getinstance('world'); // $a === $c $d = goodbye::getinstance(); $e = goodbye::getinstance();// $d === $e $f = goodbye::getinstance('your'); // $d !== $f
(三)工厂方法模式(factory method)
● 定义
将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类
● 代码示例 : 小成有一间塑料加工厂(仅生产 a 类产品);随着客户需求的变化,客户需要生产 b 类产品。改变原有塑料加工厂的配置和变化非常困难,假设下一次客户需要再发生变化,再次改变将增大非常大的成本;小成决定置办塑料分厂 b 来生产 b 类产品。
abstract class product{ public abstract function show();}//具体产品a类class producta extends product{ public function show() { echo "生产出了产品a"; }}//具体产品b类class productb extends product{ public function show() { echo "生产出了产品b"; }}abstract class factory{ public abstract function manufacture();}//工厂a类 - 生产a类产品class factorya extends factory{ public function manufacture() { return new producta(); }}//工厂b类 - 生产b类产品class factoryb extends factory{ public function manufacture() { return new productb(); }}
(四)抽象工厂模式(abstract factory)
● 定义
在不指定具体类的情况下创建一系列相关或依赖对象。 通常创建的类都实现相同的接口。 抽象工厂的客户并不关心这些对象是如何创建的,它只是知道它们是如何一起运行的。
● 代码示例 : 有两个工厂,a 工厂负责运输,b 工厂生产数码产品.
interface product{ public function calculateprice(): int;}class shippableproduct implements product{ /** * @var float */ private $productprice; /** * @var float */ private $shippingcosts; public function __construct(int $productprice, int $shippingcosts) { $this->productprice = $productprice; $this->shippingcosts = $shippingcosts; } public function calculateprice(): int { return $this->productprice + $this->shippingcosts; }}class digitalproduct implements product{ /** * @var int */ private $price; public function __construct(int $price) { $this->price = $price; } public function calculateprice(): int { return $this->price; }}class productfactory{ const shipping_costs = 50; public function createshippableproduct(int $price): product { return new shippableproduct($price, self::shipping_costs); } public function createdigitalproduct(int $price): product { return new digitalproduct($price); }}
(五)简单工厂模式(simple factory)
● 定义
简单工厂模式是一个精简版的工厂模式。工厂角色-具体产品-抽象产品
● 代码示例 :
一个农场,要向市场销售水果。农场里有三种水果 苹果、葡萄,我们设想:1、水果有多种属性,每个属性都有不同,但是,他们有共同的地方 | 生长、种植、收货、吃。将来有可能会增加新的水果、我们需要定义一个接口来规范他们必须实现的方法.
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 true; }}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;}
(六)原型模式(prototype)
● 定义
相比正常创建一个对象 (new foo () ),首先创建一个原型,然后克隆它会更节省开销。
● 代码示例 : 为每一本书设置标题
abstract class bookprototype{ /** * @var string */ protected $title = 0; /** * @var string */ protected $category; abstract public function __clone(); public function gettitle(): string { return $this->title; } public function settitle($title) { $this->title = $title; }}class barbookprototype extends bookprototype{ /** * @var string */ protected $category = 'bar'; public function __clone() { }}class foobookprototype extends bookprototype{ /** * @var string */ protected $category = 'foo'; public function __clone() { }}$fooprototype = new foobookprototype();$barprototype = new barbookprototype();for ($i = 5; $i < 10; $i++) { $book = clone $fooprototype; $book->settitle('foo book no ' . $i); var_dump(new foobookprototype == $book);}for ($i = 0; $i < 5; $i++) { $book = clone $barprototype; $book->settitle('bar book no ' . $i); var_dump(new barbookprototype == $book);}
(七)对象池模式(pool)
● 定义
对象池可以用于构造并且存放一系列的对象并在需要时获取调用。在初始化实例成本高,实例化率高,可用实例不足的情况下,对象池可以极大地提升性能。在创建对象(尤其是通过网络)时间花销不确定的情况下,通过对象池在短期时间内就可以获得所需的对象。
● 代码示例
class factory { protected static $products = array(); public static function pushproduct(product $product) { self::$products[$product->getid()] = $product; } public static function getproduct($id) { return isset(self::$products[$id]) ? self::$products[$id] : null; } public static function removeproduct($id) { if (array_key_exists($id, self::$products)) { unset(self::$products[$id]); } }}factory::pushproduct(new product('first'));factory::pushproduct(new product('second'));print_r(factory::getproduct('first')->getid());// firstprint_r(factory::getproduct('second')->getid());// second
(八)建造者模式(builder)
● 定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
● 2)代码示例 建造相同标准的卡车和汽车。类似于变形金刚,相同的零件进行不同的组合.
● 分为 director 导演者,负责构建、builderinterface 构建接口,规范建造标准、truckbuilder 构建卡车类 carbuilder 构建汽车类
vehicle 零部件公共类、truck car engine wheel door 零部件类、directortest 测试类
class director{ public function build(builderinterface $builder): vehicle { $builder->createvehicle(); $builder->adddoors(); $builder->addengine(); $builder->addwheel(); return $builder->getvehicle(); }}interface builderinterface{ public function createvehicle(); public function addwheel(); public function addengine(); public function adddoors(); public function getvehicle(): vehicle;}class truckbuilder implements builderinterface{ /** * @var truck */ private $truck; public function adddoors() { $this->truck->setpart('rightdoor', new door()); $this->truck->setpart('leftdoor', new door()); } public function addengine() { $this->truck->setpart('truckengine', new engine()); } public function addwheel() { $this->truck->setpart('wheel1', new wheel()); $this->truck->setpart('wheel2', new wheel()); $this->truck->setpart('wheel3', new wheel()); $this->truck->setpart('wheel4', new wheel()); $this->truck->setpart('wheel5', new wheel()); $this->truck->setpart('wheel6', new wheel()); } public function createvehicle() { $this->truck = new truck(); } public function getvehicle(): vehicle { return $this->truck; }}class carbuilder implements builderinterface{ /** * @var car */ private $car; public function adddoors() { $this->car->setpart('rightdoor', new door()); $this->car->setpart('leftdoor', new door()); $this->car->setpart('trunklid', new door()); } public function addengine() { $this->car->setpart('engine', new engine()); } public function addwheel() { $this->car->setpart('wheellf', new wheel()); $this->car->setpart('wheelrf', new wheel()); $this->car->setpart('wheellr', new wheel()); $this->car->setpart('wheelrr', new wheel()); } public function createvehicle() { $this->car = new car(); } public function getvehicle(): vehicle { return $this->car; }}abstract class vehicle{ /** * @var object[] */ private $data = []; /** * @param string $key * @param object $value */ public function setpart($key, $value) { $this->data[$key] = $value; }}class truck extends vehicle{}class car extends vehicle{}class engine extends vehicle{}class wheel extends vehicle{}class door extends vehicle{}class directortest{ public function testcanbuildtruck() { $truckbuilder = new truckbuilder(); return (new director())->build($truckbuilder); } public function testcanbuildcar() { $carbuilder = new carbuilder(); return (new director())->build($carbuilder); }}$directortest = new directortest();var_dump($directortest->testcanbuildtruck());var_dump($directortest->testcanbuildcar());
以上就是php设计模式(创建型)的详细内容。
