包括如下五种:php
抽象工厂css
生成器html
工厂方法设计模式
原型编辑器
单例this
咱们选择工厂方法和原型模式做为将用PHP实现的建立型设计的例子
工厂方法模式是这5个设计模式中惟一的一种类设计模式
原型模式属于对象类模式,可使用PHP_clone方法实现。首先基于原型实例化(建立)一个对象,而后由这个实例化对象进一步克隆其余对象
使用建立型模式时,最有意思的是,当程序和系统愈来愈依赖于对象组合而不是依赖于类继承时,建立型模式中的程序变成由对象构成的系统,而对象又由其余对象组合而成,因此任何单个对象的建立都不该该依赖于建立者spa
概念:工厂方法模式就是要建立某种东西,对于工厂方法模式,要建立的东西是一个产品,这个产品与建立它的类之间不存在绑定,为了保持这种松耦合,客户会经过一个工厂发出请求,再由工厂建立所请求的产品。利用工厂方法模式,请求者发出请求,而不具体建立产品。
什么时候使用:若是实例化对象的子类可能变化,就要使用工厂方法模式
Why:对象的数目和类型都是未知的,一个类没法预计它要建立的对象数目,因此你不但愿类与它要建立的类紧密绑定设计
案例模型:code
步骤:orm
第一步是创建工厂:Creator接口
<?php //Creator.php abstract class Creator{ protected abstract function factoryMethod(); public function startFactory(){ $mfg = $this->factoryMethod(); return $mfg; } } ?>
注意到,伪代码注释提示startFactory()方法须要返回一个产品(product),在实现中startFactory()但愿factoryMethod()返回一个产品对象,因此,factoryMethod()的具体实现要构建并返回由一个按Product接口实现的产品对象
下面有两个工厂类扩展了Creator,并实现了factoryMethod()方法,factoryMethod()实现经过一个Product方法(getProperties())返回一个文本或图像产品,TextFactory和GraphicFactory实现中加入了这些内容
<?php //TextFactory.php include_once('Creator.php'); include_once('TextProduct.php'); class TextFactory extends Creator{ protexted function factoryMethod(){ $product = new TextProduct(); return ($product->getProperties()); } } ?>
<?php //TextFactory.php include_once('Creator.php'); include_once('GraphicProduct.php'); class GraphicFactory extends Creator{ protexted function factoryMethod(){ $product = new GraphicProduct(); return ($product->getProperties()); } } ?>
工厂方法设计模式中的第二个接口是Product。因为这是第一个实现,也是最简单的实现,全部文本和图像属性都只实现一个方法getProperties():创建方法而无属性,咱们能够明确想要用这个方法作什么(好比能够有个返回值),只要方法名和可见性与签名一致就不会有问题
<?php //Product.php interface Product{ public function getProperties(); } ?>
能够利用这个实现,使得同一个方法getProperties()多态,分别返回图像和文字,以下所示
<?php //TextProduct.php include_once('Prouduct.php'); class TextProduct implements Product{ private $mfgProduct; public function getProperties(){ $this->mfgProduct = "This is a Text<br"; return $this->mfgProduct; } } ?>
<?php //Graphic.php include_once('Product.php'); class GraphicProduct implements Product{ private $mfgProduct; public function getProperties(){ $this->mfgProduct = "This is a Graphic<br>"; return $this->mfgProduct; } } ?>
上面你看到的This is a Graphic以及This is text,能够替换成你想放入的其它东西,工厂设计会建立这个对象,并把它返回给Client来使用。
这两个工厂和产品分别覆盖了抽象方法,来建立两个不一样的工厂和产品,它们都符合所实现的接口
客户
这个模式最后一个参与者是隐含的(上面模型图中颜色较淡的框):客户。咱们并不但愿Client类直接作出产品请求。实际上,咱们但愿可以经过Creator接口作出请求,这样一来,若是之后咱们增长产品或者工厂,客户能够作一样的请求来获得更多类型的产品,而不会破坏这个应用
<?php //Client.php include_once('GraphicFactory.php'); include_once('TextFactory.php'); class Client{ private $someGraphicObject; private $someTextObject; public function __construct(){ $this->someGraphicObject = new GraphicFactory(); echo $this->someGraphicObject->startFactory(); $this->someTextObject = new TextFactory(); echo $this->someTextObject->startFactory(); } } $worker = new Client(); ?>
注意Client对象并无向产品直接作出请求,而是经过工厂来请求,重要的是,客户并不实现产品特性,而留给产品实现来体现。
在本章有个例子,是对上面代码的改进,也能够称做是在工厂中修改产品,可是本猿觉得,例子彷佛举的不是很好,它把Html代码嵌套在php代码中,放在了产品类下的getProperties方法中,以供客户调用的时候返回,因此我我的以为这种方法不是很好,一大段代码放在php中,也不方便编辑器编辑。设计模式是为了加快开发速度,这样的方法我拔苗助长。做者是专家,可能也有出于其它考虑。不过里面有一个观点我仍是赞成的,其中有一个辅助类的观点。
所谓辅助类,就是把一些任务给一个单独的对象来处理,而不是结合到某个参与者中。相似地,若是须要重用一组HTML标记,能够把它们打包到另外一个对象中以便重用。下面是一个例子
<?php class FormatHelper{ private $topper; private $bottom; public function addTop(){ $this->topper = "<!doctype html><html><head> <link rel='stylesheet' type='text/css' href='products.css'/> <meta charset='UTF-8'> <title>Map Factory</title> </head> <body>"; return $this->topper; } public function closeUp(){ $this->bottom = "</body></html>"; return $this->bottom; } } ?>
上图与以前的类图不一样,它们完成一样的目标,不过它们的实现有所不一样。这就是参数化工厂方法设计模式(上图)与通常的工厂方法设计模式(原类图)的主要区别之一,即客户包含工厂和产品的引用。在参数化请求中,Client类必须指定产品,而不仅是产品工厂,factoryMethod()操做中的参数是由客户传入的一个产品,因此客户必须指出它想要的具体产品,不过,这个请求仍然经过Creator接口发出,因此,尽管客户包含一个产品引用,但经过Creator,客户仍与产品分离
对于大多数请求,参数化工厂方法更为简单,由于客户只须要处理一个具体工厂,工厂方法操做有一个参数,指示须要建立的产品。而在原来的设计中,每一个产品都有本身的工厂,不须要另外传递参数,产品实现依赖于各个产品的特定工厂。
要从参数化工厂方法设计模式实现多个产品,只需使用Product接口实现多个具体产品,另外,因为具体产品要同时包含文本和图像,因此在这个例子中,并非分别有这两个单独的产品,能够创建一个类,将文本和图像做为一个赞成的实体来处理,这并不违反单一职责原则,即每一个类应当只有一个职责。对于这个类来讲,这个单一职责就是显示描述一个区域的文本和图像
新工厂与原来的工厂相似,不过它们还包含一个参数和代码提示。
<?php //Creator.php abstract class Creator{ protected abstract function factoryMethod(Product $product); public function doFactory($productNow){ $countryProduct = $productNow; $mfg = $this->factoryMethod($countryProduct); return $mfg; } } ?>
新的Creator抽象类中能够看到,factoryMethod()和startFactory操做都须要一个参数。另外代码提示只是了一个Product对象,而不是Prodcut一个特定实现,因此能够接受Product的任何具体实例,下面来看看具体的建立者CountryFactory
<?php //CountryFactory.php include_once('Creator.php'); inlcude_once('Product.php'); class CountryFactory extends Creator{ private $country; protected function factoryMethod(Product $product){ $this->country = $product; return ($this->country->getProperties()); } } ?>
这个具体建立者包含一个私有变量$country,其中包含客户请求的特定产品,它再使用Product方法getProperties()将产品返回给客户
与试图让任意数目的类和对象都保持不变相比,保持接口不变要容易得多。正是由于这个缘由,使用工厂方法模式能够简化复杂的建立过程,关键就在于它在维持一个公共接口。
本文参考书籍:《Learnig PHP设计模式》第2部分第5章