创建型模式

创建型模式

ABFPS(AbstractFactory、Builder、Factory Method、Prototype、Singleton)

单例模式(Singleton)

确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

通过阻止外部实例化和修改,来控制所创建的对象的数量。

目的:

希望对象只创建一个实例,并且提供一个全局的访问点。

1.私有构造函数 - 其他类不能实例化一个新的对象。

2.私有化引用 - 不能进行外部修改。

3.公有静态方法是唯一可以获得对象的方式。

懒汉模式

调用取得实例方法的时候才会实例化对象

PHP示例

class Singleton {
    private static $instance = null;

    public static function getInstance() {
        if ( ! (self::$instance ) ) {
            self::$instance = new self();
        }  
        return self::$instance;
    }

    //空构造函数  
    private function __construct() {  

    }

    //空克隆成员函数
    private function __clone() {

    }

    public function test() {
        echo "test";
    } 
}
Singleton::getInstance()->test();

饿汉模式

加载类的时候会连带着创建实例

PHP中不支持饿汉式的单例模式

因为PHP不支持在类定义时给类的成员变量赋予非基本类型的值。如表达式,new操作等等

java示例

public class Singleton {
    private Singleton(){}
    private static Singleton instance = new Singleton();
    public static Singleton getInstance() {
    return instance;
    }
}

工厂模式(Factory Method)

定义一个用于创建对象的接口,让子类决定实例化哪一个类

  • 通过工厂模式,将产品的实例化封装起来

  • 调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心

  • 降低耦合度

代码示例

interface IProduct {  
    public function productMethod();  
}  

class Product implements IProduct {  
    public function productMethod() {  
        echo("产品");  
    }  
}  

interface IFactory {  
    public function createProduct();  
}  

class Factory implements IFactory {  
    public function createProduct() {  
        return new Product();  
    }  
}

class Client {  
    public static function main() {  
        $factory = new Factory();  
        $prodect = $factory->createProduct();  
        $prodect->productMethod();  
    }  
}
Client::main();

组装汽车

不使用工厂模式

class Engine {  
    public function getStyle(){  
        echo("这是汽车的发动机");  
    }  
}  
class Underpan {  
    public function getStyle(){  
        echo("这是汽车的底盘");  
    }  
}  
class Wheel {  
    public function getStyle(){  
        echo("这是汽车的轮胎");  
    }  
}
class Car {
    function __construct( $underpan, $wheel, $engine ) {
        $this->underpan = $underpan;
        $this->wheel = $wheel;
        $this->engine = $engine;
    }

    public function show() {
        $this->underpan->getStyle();
        $this->wheel->getStyle();
        $this->engine->getStyle();
    }   
}
class Client {  
    public static function main() {  
        $engine = new Engine();  
        $underpan = new Underpan();  
        $wheel = new Wheel();  
        $car = new Car($underpan, $wheel, $engine);  
        $car->show();  
    }  
} 

Client::main();

工厂模式

class Engine {  
    public function getStyle(){  
        echo("这是汽车的发动机");  
    }  
}

class Underpan {  
    public function getStyle(){  
        echo("这是汽车的底盘");  
    }  
} 

class Wheel {  
    public function getStyle(){  
        echo("这是汽车的轮胎");  
    }  
}

class Car {
    function __construct( $underpan, $wheel, $engine ) {
        $this->underpan = $underpan;
        $this->wheel = $wheel;
        $this->engine = $engine;
    }

    public function show() {
        $this->underpan->getStyle();
        $this->wheel->getStyle();
        $this->engine->getStyle();
    }   
}

interface IFactory {  
    public function createCar();  
}

class Factory implements IFactory {  
    public function createCar() {  
        $engine = new Engine();  
        $underpan = new Underpan();  
        $wheel = new Wheel();  
        $car = new Car($underpan, $wheel, $engine);  
        return $car;  
    }  
}

class Client {  
    public static function main() {  
        $factory = new Factory();  
        $car = $factory->createCar();  
        $car->show();  
    }  
}
Client::main();

angular的工厂调用

angular.module('myModule', []).  
  config(['depProvider', function(depProvider){  
    ...  
  }]).  
  factory('serviceId', ['depService', function(depService) {  
    ...  
  }]).  
  directive('directiveName', ['depService', function(depService) {  
    ...  
  }]).  
  filter('filterName', ['depService', function(depService) {  
    ...  
  }]).  
  run(['depService', function(depService) {  
    ...  
  }]);  

抽象工厂模式(AbstractFactory)

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类

抽象工厂模式是在工厂模式的基础上增加的一层抽象概念。如果比较抽象工厂模式和工厂模式,我们不难发现前者只是增加了一层抽象的概念。抽象工厂是一个父类工厂,可以创建其它工厂类。故我们也叫它“工厂的工厂”。

interface CPU {
    function process();
}  

interface CPUFactory {
    function produceCPU();
} 

class AMDFactory implements CPUFactory {
    public function produceCPU() {
        return new AMDCPU();
    }
}

class IntelFactory implements CPUFactory {
    public function produceCPU() {
        return new IntelCPU();
    }
} 

class AMDCPU implements CPU {
    public function process() {
        print_r("AMD is processing...");
    }
} 

class IntelCPU implements CPU {
    public function process() {
        print_r("Intel is processing...");
    }
} 

//创建工厂的工厂
class Computer {
    private $cpu;

    function __construct($factory) { 
        $this->factory = $factory;
        $this->Computer();
    }
 
    public function Computer() {
        $this->cpu = $this->factory->produceCPU();
        $this->cpu->process();
    }
} 

class Client {
    public static function main() {
        new Computer(self::createSpecificFactory());
    }
 
    public static function createSpecificFactory() {
        $sys = 0;
        if ($sys == 0) 
            return new AMDFactory();
        else
            return new IntelFactory();
    }
}

Client::main();

创建者模式(Builder)

将一个复杂对象的构建和表示分离,使得同样的构建过程可以构建不同的表示。

将构建复杂对象的过程与组成对象的部件解耦。

建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。

  • 产品类:一般是一个较为复杂的对象。包含定义组件的类,包括将这些组件装配成产品的接口。

  • 抽象建造者:用来规范产品对象各个组成成分的建造。至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。

  • 具体建造者: 实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。

  • 指导者:调用具体的建造者创建产品对象。

代码示例

class Product {  
    private $name;  
    private $type;
    public function showProduct() {  
       echo("名称:".$this->name);  
       echo("型号:".$this->type);   
    }
    public function setName( $name ) {    
        $this->name = $name;  
    }
    public function setType( $type ) {
        $this->type = $type;  
    }  
} 

abstract class Builder {  
    public abstract function setPart($arg1, $arg2);  
    public abstract function getProduct();  
} 

class ConcreteBuilder extends Builder {  
    private $product;

    function __construct() { 
        $this->product = new Product();
    } 
      
    public function getProduct() {  
        return $this->product;  
    }  
  
    public function setPart($arg1, $arg2) { 
        $this->product->setName($arg1);  
        $this->product->setType($arg2);  
    }  
} 

class Director {  
    private $builder;
    function __construct() { 
        $this->builder = new ConcreteBuilder();
    }  
    public function getAProduct(){  
        $this->builder->setPart("宝马汽车","X7");  
        return $this->builder->getProduct();  
    }  
    public function getBProduct(){  
        $this->builder->setPart("奥迪汽车","Q5");  
        return $this->builder->getProduct();  
    }  
}

class Client { 
    public static function main(){  
        $director = new Director();  
        $product1 = $director->getAProduct();  
        $product1->showProduct();  
  
        $product2 = $director->getBProduct();  
        $product2->showProduct();  
    }  
}
Client::main();

建造者模式的优点

  • 建造者模式的封装性很好。

  • 建造者模式很容易进行扩展,新的需求,通过实现一个新的建造者类就可以完成

建造者模式与工厂模式的区别

把指导者类看做是最终调用的客户端,那么剩余的部分就可以看作是一个简单的工厂模式

创建模式着重于逐步将组件装配成一个成品并向外提供,而抽象工厂模式着重于得到产品族中相关的多个产品对象。

原型模式(Prototype)

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。

原型模式主要用于对象的复制,它的核心是就是原型类Prototype。

实现Cloneable接口。实现了此接口的类上使用copy方法。

interface Cloneable {
  function copy();
}

class Prototype implements Cloneable {
    public function copy(){    
        return clone $this;

        /**
         * 深拷贝
         */
        /*
        $serialize_obj = serialize($this);  //序列化
        $clone_obj = unserialize($serialize_obj);   //反序列化
        return $clone_obj; */
    }  
}  
  
class ConcretePrototype extends Prototype{  
    public function show(){  
        echo("原型模式实现类");  
    }  
}  
  
class Client {  
    public static function main(){  
        $cp = new ConcretePrototype();  
        for($i=0; $i< 10; $i++){  
            $clonecp = $cp->copy();  
            $cp->show();  
        }  
    }  
}

Client::main();

原型模式的优点

  • 使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

  • 简化对象的创建

使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。

单例模式与原型模式是冲突的。

设计模式5 创建型模式1