创建型模式主要是为了解决创建对象的时候的问题而存在的。
创建型设计模式有两个主导思想:一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合方式。
创建型模式主要分为以下五种:
- 简单工厂模式(Simple Factory)和工厂方法模式(Factory method)
- 抽象工厂模式(Abstract factory)
- 单例模式(Singleton)
- 建造者模式(Builder)
- 原型模式(Prototype)
单例模式
单例模式的重点是,对象有且仅有一次实例化。 组成部分主要是:
- 私有化成员变量,存储实例化的对象
- 私有化构造方法,防止外部创建
- 私有化克隆方法,防止对象复制
- 公有的静态方法,对外界提供实例
上代码噻~
<?php
class Test{
private static $instance = NULL;
private function __construct(){}
private function __clone(){}
public static function getInstance(){
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
案例: 数据库连接
简单工厂模式
工厂模式:父类中提供一个创建对象的接口,用来允许子类决定实例化的类型
简单工厂模式:有抽象类,实现类,工厂类,把创建类这部分放在工厂类里面
<?php
abstract class Math{
abstract function getValue($x, $y){}
}
class Add extends Math
{
public function getValue($x, $y) {
return $x + $y;
}
}
class Sub extends Math{
public function getValue($x, $y) {
return $x - $y;
}
}
class MyMath{
static function getClass($type) {
switch ($type) {
case "+":
return new Add();
case "-":
return new Sub();
}
}
}
$myMath = MyMath::getClass("+");
return $myMath->getValue(2, 3);
好处是调用简单, 创建对象和实例化分开,但是新增功能的时候需要修改工厂类,但是对其他部分代码不影响,定位问题也会更快。
工厂方法模式
封装类中不变的部分,提取善变的部分为独立类,通过依赖注入的方式达到解耦,复用和方便后期维护
- 抽象工厂-------工艺的流程和顺序
- 具体工厂-------隐藏背后产品的细节
- 抽象产品-------产品生产工艺
- 具体产品-------具体产品怎么生产,可以有个性化设置,只要工序按照抽象标准生产即可
<?php
abstract class Math{
abstract function getValue($x, $y){}
}
class Add extends Math
{
public function getValue($x, $y) {
return $x + $y;
}
}
class Sub extends Math{
public function getValue($x, $y) {
return $x - $y;
}
}
abstract class iFactory{
abstract function getObj(){}
}
class FactoryAdd extends iFactory{
static function getObj(){
return new Add();
}
}
class FactorySub extends iFactory{
static function getObj(){
return new Sub();
}
}
$client = FactoryAdd::getObj();
return $client->getValue(2, 3);
应用例子:支付的话,支付宝支付,银行支付,微信支付。可以看作是一个典型的例子。 另一个例子就是PHP链接数据库的时候,不管是mysql还是sqlserver都抽象成同样的链接方式,查询方式,忽略底层不同的实现方式。
抽象工厂模式
产品类:
<?php
interface AutoProduct
{
public function dirve();
}
class AudiA4Product implements AutoProduct
{
public function dirve()
{
echo "开奥迪A4"."<br>";
}
}
class BenzC200Product implements AutoProduct
{
public function dirve()
{
echo "开奔驰C200"."<br>";
}
}
interface AirCondition
{
public function blow();
}
class GreeAirCondition implements AirCondition
{
public function blow()
{
echo "吹格力空调某型号"."<br>";
}
}
class HaierAirCondition implements AirCondition
{
public function blow()
{
echo "吹海尔空调某型号"."<br>";
}
}
工厂类:
interface Factory
{
public function getAuto();
public function getAirCondition();
}
class AFactory implements Factory
{
public function getAuto()
{
return new AudiA4Product();
}
public function getAirCondition()
{
return new HaierAirCondition();
}
}
class BFactory implements Factory
{
public function getAuto()
{
return new BenzC200Product();
}
public function getAirCondition()
{
return new GreeAirCondition();
}
}
$factoryA = new AFactory();
$factoryB = new BFactory();
$auto_carA = $factoryA->getAuto();
$auto_airA = $factoryA->getAirCondition();
$auto_carB = $factoryB->getAuto();
$auto_airB = $factoryB->getAirCondition();
$auto_carA->dirve();
$auto_airA->blow();
$auto_carB->dirve();
$auto_airB->blow();
?>
对比 工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。
简单工厂 :用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力) 工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品) 抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
建造者模式
定义了处理其他对象的复杂构建的对象设计 将一个复杂对象的建造和调用者分离。调用者只需要给出指定对象的类型和那天。 建造者模式负责按照顺序创建复杂的对象/ 组成部分:
建造请求(Builder):定义一个抽象接口,规范产品各个组成成分的建造,包括建造方法和返回结果的方法 具体建造者(Concrete Builder):实现builder定义的方法,建造结束之后返回一个产品实例 指挥者角色(Director):调用具体的建造者角色建造那个产品, 产品角色(Product):在指挥者的指导下由具体建造者建造的那个复杂的对象 优点: 易于解耦,建造者模式可以很好的将一个对象的实现和相关业务逻辑分离,将产品本身和创建过程分类,可以使用相同的过程来创建不同的产品。 易于精确的控制对象,将负责对象的创建划分在不同的方法中,过程更加清晰 易于扩展,增加新的建造者无需修改原来的类库 缺点: 建造者模式的产品有较多的共同点,组成部分类似,如果产品之间差异较大则不适合,如果产品的内部变化复杂,需要定义更多的具体建造者来配合,导致系统变得庞大 建造者接口修改会导致所有执行类的修改 使用场景: 需要生成的产品对象有复杂的内部结构,属性相互依赖,建造者模式可以强迫生成顺序 在对象创建过程中会使用到系统的一些其他对象,这些对象在产品创建过程中不易得到
<?php
abstract class Builder{
public abstract function buildWheel(){}
public abstract function buildChair(){}
public abstract function buildEngine(){}
public abstract function getCar(){}
}
class Director{
public function assemble(Builder $builder) {
$builder->buildChair();
$builder->buildWheel();
$builder->buildEngine();
}
}
class Car{
private $buildList = [];
public function add($part) {
$this->buildList[] = $part;
}
public function show() {
foreach ($this->buildList as $key => $builder) {
echo '组件' . $builder . '安装好了</br>';
}
print_r('组装完毕');
}
}
class ConcreteBuilder extends Builder{
private $car;
public function __construct() {
$this->car = new Car();
}
public function buildChair() {
$this->car->add('装椅子');
}
public function buildWheel() {
$this->car->add('装轮子');
}
public function buildEngine() {
$this->car->add('装引擎');
}
public function getCar()
{
return $this->car;
}
}
class ConcreteBuilder2 extends Builder{
private $car;
public function __construct() {
$this->car = new Car();
}
public function buildChair() {
$this->car->add('装好椅子');
}
public function buildWheel() {
$this->car->add('装好轮子');
}
public function buildEngine() {
$this->car->add('装好引擎');
}
public function getCar()
{
return $this->car;
}
}
$director = new Director();
$builder = new ConcretrBuilder();
$director->assemble($builder);
$car = $builder->getCar();
$builder2 = new ConcretrBuilder2();
$director->assemble($builder2);
$car2 = $builder2->getCar();
原型模式
通过创建一个原型对象,然后复制原型对象来避免通过标准的方式(这里说的是new)创建大量的对象产生的开销。
代码:
<?php
abstract class CloneMe
{
public $name;
public $picture;
abstract function __clone();
}
class Person extends CloneMe
{
public function __construct()
{
$this->picture = 'CloneMan.png';
$this->name = 'Origin';
public function display()
{
echo "<img src = $this->picture>";
echo "<br/> $this->name<p/>";
}
function __clone(){
}
}
}
$worker = new Person();
$worker->display();
$slacker = clone $worker;
$slacker->name = "Cloned";
$slacker->display();
有一个小的tips就是,克隆的时候并不会执行构造函数。
原型模式的优缺点 优点: 可以在运行时刻增加和删除产品 可以改变结构以指定新对象 可以改变值以指定新对象 减少子类的构造 用类动态配置应用 缺点: 每个类必须配一个克隆方法。 也就是说,当实例化的类是在运行时刻才知道的时候,比较适合原型模式。
|