澳门新浦京电子游戏:PHP 中的设计模式详解

本文主要讨论下Web开发中,准确而言,是PHP开发中的相关的设计模式及其应用。有经验的开发者肯定对于设计模式非常熟悉,但是本文主要是针对那些初级的开发者。首先我们要搞清楚到底什么是设计模式,设计模式并不是一种用来解释的模式,它们并不是像链表那样的常见的数据结构,也不是某种特殊的应用或者框架设计。事实上,设计模式的解释如下:

本文作者: 伯乐在线 –
伯小乐
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

前言

很久前就一直想总结下常用的设计模式,但是各种原因一直拖到现在,下面我尝试用自己的理解去解释常用的设计模式,旨在让自己对常用设计模式有一个直观认识,过后回来能看懂并理解这些常用设计模式,当然如果这篇文章能帮到想了解设计的同学那就更好不过了。


descriptions of communicating objects and classes that are customized
to solve a general design problem in a particular context.

学习设计模式的方法有很多。全面深入地学习,可以选择经典设计模式书籍。或者通过简短、清晰的教程快速了解设计模式。本文整理了23个设计模式的简明教程,其中多篇以讲故事的方式来学习设计模式。

概念介绍

设计模式分为三大类:

  • 创建型模式(Creational
    Pattern):创建型模式对类的实例化过程进行了抽象,将软件模块中对象的创建和对象的使用分离。使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不需要清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。
    创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。
    设计模式中属于创建型模式的有:
    单例模式、建造者模式、工厂方法模式、抽象工厂模式、原型模式。
    其中常用的有:

    • 单例模式:保证一个类只有一个实例,并且提供对这个实例的全局访问方式。
    • 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
    • 工厂方法模式:允许一个类的实例化推迟到子类中进行。
    • 抽象工厂模式:提供一个创建相关或依赖对象的接口,而不指定对象的具体类。

    这几个模式在这篇文章中都会有介绍。

  • 结构型模式(Structural
    Pattern):结构型模式描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构。
    结构型模式可以分为类结构型模式和对象结构型模式:
    类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。
    对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。
    根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。
    设计模式中属于结构型模式的有:适配器模式、代理模式、享元模式、外观模式、桥接模式、组合模式、装饰器模式。
    其中常用的有:

    • 适配器模式:将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
    • 代理模式:给某一个对象提供一个代理,并由代理对象控制对原对象的引用,它是一种对象结构型模式。
    • 享元模式:运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

这几个模式会在下篇文章中介绍。

  • 行为型模式(Behavioral
    Pattern):行为型模式是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象
    之间的交互。在系统运行时,对象并不是孤立的,它们可以通过相互通信与协作完成某些复杂功能,一个对象在运行时也将影响到其他对象的运行。
    设计模式中属于行为型模式的有:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
    其中常用的有:

    • 策略模式:定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。
    • 观察者模式:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

另一方面,设计模式提供了一种广泛的可重用的方式来解决我们日常编程中常常遇见的问题。设计模式并不一定就是一个类库或者第三方框架,它们更多的表现为一种思想并且广泛地应用在系统中。它们也表现为一种模式或者模板,可以在多个不同的场景下用于解决问题。设计模式可以用于加速开发,并且将很多大的想法或者设计以一种简单地方式实现。当然,虽然设计模式在开发中很有作用,但是千万要避免在不适当的场景误用它们。

创建型模式

一、Singleton,单例模式

《案例:模式的秘密—单例模式(视频)》

设计模式是前辈们在多年开发工作中经验的总结,可以提高代码的可重用性、可靠性和规范性,让代码更容易理解,而单例模式是其中最重要、最简单、最常用的设计模式之一,让我们一起来揭开它的神秘面纱吧。

《讲故事,学(Java)设计模式—单例模式》

单例模式是Java中最常用的设计模式之一,它通过阻禁止外部实例化和修改,对象的方式来控制所创建的对象的数量。这个概念可以被广泛地推广到仅使用有一个现存的对象能更高效运行的系统,或者是限制在若干个对象实例化为特定的数目的高效系统环境系统中。

二、Abstract Factory,抽象工厂

《讲故事,学(Java)设计模式—抽象工厂模式》

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

三、Factory,工厂模式

《讲故事,学(Java)设计模式—工厂模式》

工厂模式是根据不同的参数创建对象。例如用工厂创建人。
如果我们想要一个男孩,工厂就会为我们生产一个男孩;如果我们需要一个女孩,工厂则会为我们生产一个女孩。工厂会根据不同的参数,为我们提供不同的物品。

四、Builder,建造者模式

澳门新浦京电子游戏,《讲故事,学(Java)设计模式—建造者模式》

建造者模式的关键特性是它将一个建造过程分解成很多步骤,也可以说,每个产品的建造会遵循同样的流程,不过流程内的每一个步骤都不尽相同。

五、Prototype,原型模式

《讲故事,学(Java)设计模式—原型模式》

原型模式被用在频繁调用且极其相似的对象上,它会克隆对象并设置改变后的属性,而且消耗的资源较少。

单例模式

单例模式是最常用的设计模式之一,是为了保证单例对象的类只有一个实例存在,并保证整个系统只需要拥有一个全局对象。

目前常见的设计模式主要有23种,根据使用目标的不同可以分为以下三大类:

行为型模式

六、Iterator,迭代器模式

《Java Design Pattern:
Iterator》

七、Observer,观察者模式

《讲故事,学(Java)设计模式—观察者模式》

简而言之,观察者模式=发布者+注册者。观察者模式用来对GUI中的动作做侦听。Swing
GUI的例子就表明了动作侦听是怎样实现观察者模式的。

八、Template Method,模板方法

《案例:模式的秘密—模板方法模式(中文视频)》

模板方法模式是在日常开发中使用最为广泛的设计模式之一。通过本视频,你可以了解什么是模板方法模式,如何用
Java 语言实现模板方法模式。@Arthur
将用简单生动的例子带你领略模板方法模式的真意,最后还将用实际的行业案例告诉你模板方法模式的强大功能。

九、Command,命令模式

《Java Design Pattern:
Command》

十、State,状态模式

《Java Design Pattern:
State》

十一、Strategy,策略模式

《Java Design Pattern:
Strategy》

十二、Chain of Responsibility,职责链模式

《Java Design Pattern: Chain of
Responsibility》

十三、Mediator,中介者模式

《Java Design Pattern:
Mediator》

十四、Visitor,访问者模式

《Java Design Pattern:
Visitor》

十五、Interpreter,解释器模式

《Java Design Pattern:
Interpreter》

十六、Memento,备忘录模式

《Java Design Pattern:
Memento》

使用场景

确保某个类在全局中只需要存在一个对象的场景。如:访问IO和数据库时,使用单例模式可以避免浪费资源。

  • 创建模式:用于创建对象从而将某个对象从实现中解耦合。
  • 架构模式:用于在不同的对象之间构造大的对象结构。
  • 行为模式:用于在不同的对象之间管理算法、关系以及职责。

结构型模式

十七、Composite,组合模式

《Java Design Pattern:
Composite》

十八、Facade,外观模式

《Java Design Pattern:
Facade》

十九、Proxy,代理模式

《Java Design Pattern Story for Proxy – A Slutty
Lady》

二十、Adapter,适配器模式

《案例:模式的秘密—适配器模式(中文视频)》

所谓适配器,就是连接“源”和“目标”的纽带。本课程由生活中常见的例子入手,讲述适配器模式的组成和应用,为你的
Java 达人锻造添砖加瓦

二十一、Decrator,装饰模式

《Java Design Pattern: Decorator – Decorate your
girlfriend》

二十二、Bridge,桥模式

《讲故事,学(Java)设计模式—桥接模式》

简单来讲,桥接模式是一个两层的抽象。桥接模式是用于“把抽象和实现分开,这样它们就能独立变化”。
桥接模式使用了封装、聚合,可以用继承将不同的功能拆分为不同的类。

二十三、Flyweight,享元模式

《Java Design Pattern:
Flyweight》

赞 16 收藏 1
评论

懒汉模式

懒汉模式是声明一个静态变量,在调用对象类提供的get方法时就进行初始化,如下:

public class LazySingleton {
    private static LazySingleton mSingleton;

    public static synchronized LazySingleton getLazySingleton() {
        if (mSingleton == null) {
            mSingleton = new LazySingleton();
        }
        return mSingleton;
    }
}

懒汉模式只会在使用时才会被实例化,可以节约一定的资源,但是每次调用getLazySingleton都会进行同步,造成不必要的同步开销,这种模式一般不建议使用。

Creational Patterns

关于作者:伯小乐

澳门新浦京电子游戏 1

伯乐在线小编一枚~~~~PS:我不是@小编辑,不要问我了
个人主页 ·
我的文章 ·
261

饿汉模式

饿汉模式在类加载的时候就进行了初始化,所以类加载会稍慢,但是调用类实例时由于类已经初始化所以获取速度很快。如下:

public class HungrySingleton {
    private static HungrySingleton mSingleton = new HungrySingleton();

    public static HungrySingleton getHungrySingleton() {
        return mSingleton;
    }
}

Singleton(单例模式)

单例模式是最常见的模式之一,在Web应用的开发中,常常用于允许在运行时为某个特定的类创建一个可访问的实例。

<?php
/**
 * Singleton class
 */
final class Product
{

    /**
     * @var self
     */
    private static $instance;

    /**
     * @var mixed
     */
    public $mix;

    /**
     * Return self instance
     *
     * @return self
     */
    public static function getInstance() {
        if (!(self::$instance instanceof self)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
    }

    private function __clone() {
    }
}

$firstProduct = Product::getInstance();
$secondProduct = Product::getInstance();

$firstProduct->mix = 'test';
$secondProduct->mix = 'example';

print_r($firstProduct->mix);
// example
print_r($secondProduct->mix);
// example

在很多情况下,需要为系统中的多个类创建单例的构造方式,这样,可以建立一个通用的抽象父工厂方法:

<?php

abstract class FactoryAbstract {

    protected static $instances = array();

    public static function getInstance() {
        $className = static::getClassName();
        if (!(self::$instances[$className] instanceof $className)) {
            self::$instances[$className] = new $className();
        }
        return self::$instances[$className];
    }

    public static function removeInstance() {
        $className = static::getClassName();
        if (array_key_exists($className, self::$instances)) {
            unset(self::$instances[$className]);
        }
    }

    final protected static function getClassName() {
        return get_called_class();
    }

    protected function __construct() { }

    final protected function __clone() { }
}

abstract class Factory extends FactoryAbstract {

    final public static function getInstance() {
        return parent::getInstance();
    }

    final public static function removeInstance() {
        parent::removeInstance();
    }
}
// using:

class FirstProduct extends Factory {
    public $a = [];
}
class SecondProduct extends FirstProduct {
}

FirstProduct::getInstance()->a[] = 1;
SecondProduct::getInstance()->a[] = 2;
FirstProduct::getInstance()->a[] = 3;
SecondProduct::getInstance()->a[] = 4;

print_r(FirstProduct::getInstance()->a);
// array(1, 3)
print_r(SecondProduct::getInstance()->a);
// array(2, 4)

双重检查模式 (Double CheckLock)

DCL方式的优点是能保证在需要是单例才会初始化的同时保证线程安全。如下:

public class DCLSingleton {

    private static DCLSingleton mSingleton;

    public static DCLSingleton getDCLSingleton() {
        if (mSingleton == null) {
            synchronized (DCLSingleton.class) {
                if (mSingleton == null) {
                    mSingleton = new DCLSingleton();
                }
            }
        }
        return mSingleton;
    }
}

Registry

注册台模式并不是很常见,它也不是一个典型的创建模式,只是为了利用静态方法更方便的存取数据。

<?php
/**
* Registry class
*/
class Package {

    protected static $data = array();

    public static function set($key, $value) {
        self::$data[$key] = $value;
    }

    public static function get($key) {
        return isset(self::$data[$key]) ? self::$data[$key] : null;
    }

    final public static function removeObject($key) {
        if (array_key_exists($key, self::$data)) {
            unset(self::$data[$key]);
        }
    }
}

Package::set('name', 'Package name');

print_r(Package::get('name'));
// Package name

静态内部类单例模式

这种方式不仅能确保线程安全也能保证Singleton类的唯一性,这是推荐使用的静态内部类单例模式。

public class StaticSingleton {
    public static StaticSingleton getStaticSingleton() {
        return StaticSingletonHolder.singleton;
    }

    private static class StaticSingletonHolder {
        private static final StaticSingleton singleton = new StaticSingleton();
    }
}

Factory(工厂模式)

工厂模式是另一种非常常用的模式,正如其名字所示:确实是对象实例的生产工厂。某些意义上,工厂模式提供了通用的方法有助于我们去获取对象,而不需要关心其具体的内在的实现。

<?php

interface Factory {
    public function getProduct();
}

interface Product {
    public function getName();
}

class FirstFactory implements Factory {

    public function getProduct() {
        return new FirstProduct();
    }
}

class SecondFactory implements Factory {

    public function getProduct() {
        return new SecondProduct();
    }
}

class FirstProduct implements Product {

    public function getName() {
        return 'The first product';
    }
}

class SecondProduct implements Product {

    public function getName() {
        return 'Second product';
    }
}

$factory = new FirstFactory();
$firstProduct = $factory->getProduct();
$factory = new SecondFactory();
$secondProduct = $factory->getProduct();

print_r($firstProduct->getName());
// The first product
print_r($secondProduct->getName());
// Second product

小结

以上四种是比较常用的单例写法,单例模式在日常开发中使用很多,在Android源码中也有使用。


AbstractFactory(抽象工厂模式)

有些情况下我们需要根据不同的选择逻辑提供不同的构造工厂,而对于多个工厂而言需要一个统一的抽象工厂:

<?php

class Config {
    public static $factory = 1;
}

interface Product {
    public function getName();
}

abstract class AbstractFactory {

    public static function getFactory() {
        switch (Config::$factory) {
            case 1:
                return new FirstFactory();
            case 2:
                return new SecondFactory();
        }
        throw new Exception('Bad config');
    }

    abstract public function getProduct();
}

class FirstFactory extends AbstractFactory {
    public function getProduct() {
        return new FirstProduct();
    }
}
class FirstProduct implements Product {
    public function getName() {
        return 'The product from the first factory';
    }
}

class SecondFactory extends AbstractFactory {
    public function getProduct() {
        return new SecondProduct();
    }
}
class SecondProduct implements Product {
    public function getName() {
        return 'The product from second factory';
    }
}

$firstProduct = AbstractFactory::getFactory()->getProduct();
Config::$factory = 2;
$secondProduct = AbstractFactory::getFactory()->getProduct();

print_r($firstProduct->getName());
// The first product from the first factory
print_r($secondProduct->getName());
// Second product from second factory

建造者模式

建造者模式是一步步创建复杂对象的创建型模式,这个模式可以让用户在不知道内部构建细节的情况下,控制对象的构造流程。如汽车有车轮、方向盘、座椅还有各种小零件等,将这些部件组装成一辆汽车就是一个复杂的过程。在这个事例里汽车就是一个复杂的对象,而将汽车部件组装成汽车的过程就是复杂对象的构建流程。建造者模式将复杂对象的构建过程和部件进行了良好的解耦,将耦合度降到最低。

Object 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());
// first
print_r(Factory::getProduct('second')->getId());
// second

使用场景

  • 相同方法不同执行顺序会产生不同的事件结果时。
  • 多个部件或者零件都可以装配到一个对象中,但是产生的
    运行结果又不相同时。
  • 产品类是个复杂的对象,或产品类调用顺序不同就会产生不同的作用时。
  • 当初始化一个对象异常复杂时。

Lazy Initialization(延迟初始化)

对于某个变量的延迟初始化也是常常被用到的,对于一个类而言往往并不知道它的哪个功能会被用到,而部分功能往往是仅仅被需要使用一次。

<?php

interface Product {
    public function getName();
}

class Factory {

    protected $firstProduct;
    protected $secondProduct;

    public function getFirstProduct() {
        if (!$this->firstProduct) {
            $this->firstProduct = new FirstProduct();
        }
        return $this->firstProduct;
    }

    public function getSecondProduct() {
        if (!$this->secondProduct) {
            $this->secondProduct = new SecondProduct();
        }
        return $this->secondProduct;
    }
}

class FirstProduct implements Product {
    public function getName() {
        return 'The first product';
    }
}

class SecondProduct implements Product {
    public function getName() {
        return 'Second product';
    }
}

$factory = new Factory();

print_r($factory->getFirstProduct()->getName());
// The first product
print_r($factory->getSecondProduct()->getName());
// Second product
print_r($factory->getFirstProduct()->getName());
// The first product

例子

使用建造者模式组装一台汽车,假定一辆汽车只需要有车轮、方向盘、座椅这三个部件。那么一个汽车类就有如下几个变量和组装方法:
产品类

public class Car {

    private String mWheel;//车轮
    private String mSteering;//方向盘
    private String mSeat;//座椅

    /**
     * 组装车轮
     *
     * @param mWheel
     */
    public void setmWheel(String mWheel) {
        this.mWheel = mWheel;
    }

    /**
     * 组装方向盘
     *
     * @param mSteering
     */
    public void setmSteering(String mSteering) {
        this.mSteering = mSteering;
    }

    /**
     * 组装座椅
     *
     * @param mSeat
     */
    public void setmSeat(String mSeat) {
        this.mSeat = mSeat;
    }

    @Override
    public String toString() {
        return "Car{" +
                "mWheel='" + mWheel + ''' +
                ", mSteering='" + mSteering + ''' +
                ", mSeat='" + mSeat + ''' +
                '}';
    }
}

Builder类组装模板
一个良好的汽车组装流程应该有一套组装模板,模板包含各种控件的组装方法,这里的组装模板类如下

public abstract class Builder {
    public abstract void buildWheel(String wheel);

    public abstract void buildSteering(String settring);

    public abstract void buildSeat(String seat);

    public abstract Car createCar();
}

而要想组装一辆具体的车必须传承这套组装模板:

public class SixSixSixCarBuilder extends Builder {

    private Car mCar = new Car();

    @Override
    public void buildWheel(String wheel) {
        mCar.setmWheel(wheel);
    }

    @Override
    public void buildSteering(String steering) {
        mCar.setmSteering(steering);
    }

    @Override
    public void buildSeat(String seat) {
        mCar.setmSeat(seat);
    }

    @Override
    public Car createCar() {
        return mCar;
    }
}

然后还需要一个指挥者(Director )去规范指挥组装流程:

public class Director {

    Builder mBuild = null;

    public Director(Builder build) {
        this.mBuild = build;
    }

    public Car createCar(String wheel, String steering, String seat) {
        this.mBuild.buildWheel(wheel);
        this.mBuild.buildSteering(steering);
        this.mBuild.buildSeat(seat);
        return mBuild.createCar();
    }

}

这时候谁要造汽车只需要找到这个指挥者即可,测试如下

public class Test{
    public static void main(string[] args){

        Builder builder=new SixSixSixCarBuilder();
        Director director=new Director(builder);
        director.createCar("米其林三星轮胎","真皮方向盘","真皮座椅");

        System.out.println("汽车信息:"+builder.createCar().toString());
    }
}

Prototype(原型模式)

有些时候,部分对象需要被初始化多次。而特别是在如果初始化需要耗费大量时间与资源的时候进行预初始化并且存储下这些对象。

<?php

interface Product {
}

class Factory {

    private $product;

    public function __construct(Product $product) {
        $this->product = $product;
    }

    public function getProduct() {
        return clone $this->product;
    }
}

class SomeProduct implements Product {
    public $name;
}

$prototypeFactory = new Factory(new SomeProduct());

$firstProduct = $prototypeFactory->getProduct();
$firstProduct->name = 'The first product';

$secondProduct = $prototypeFactory->getProduct();
$secondProduct->name = 'Second product';

print_r($firstProduct->name);
// The first product
print_r($secondProduct->name);
// Second product

小结

从上面例子得出建造者模式主要有以下几个结构构成:

Builder(构造者)

构造者模式主要在于创建一些复杂的对象:

<?php

class Product {

    private $name;

    public function setName($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Builder {

    protected $product;

    final public function getProduct() {
        return $this->product;
    }

    public function buildProduct() {
        $this->product = new Product();
    }
}

class FirstBuilder extends Builder {

    public function buildProduct() {
        parent::buildProduct();
        $this->product->setName('The product of the first builder');
    }
}

class SecondBuilder extends Builder {

    public function buildProduct() {
        parent::buildProduct();
        $this->product->setName('The product of second builder');
    }
}

class Factory {

    private $builder;

    public function __construct(Builder $builder) {
        $this->builder = $builder;
        $this->builder->buildProduct();
    }

    public function getProduct() {
        return $this->builder->getProduct();
    }
}

$firstDirector = new Factory(new FirstBuilder());
$secondDirector = new Factory(new SecondBuilder());

print_r($firstDirector->getProduct()->getName());
// The product of the first builder
print_r($secondDirector->getProduct()->getName());
// The product of second builder

– Product: 产品类。

Builder:抽象Builder类,规范产品的组建,子类会继承这个类实现具体的建造流程。

  • ConcreteBulider:
    上面Builder的实现类,实现抽象Builder类定义的所有方法,并且返回一个组建好的对象。
  • Director: 指挥者类,用于统一组装流程。

实际开发中Director类经常是忽略的,直接用Builder来对对象进行组装,如下:

public class Test{
    public static void main(string[] args){

        Builder builder=new SixSixSixCarBuilder();
        builder.buildWheel("米其林三星轮胎");
        builder.buildSteering("真皮方向盘");
        builder.buildSeat("真皮座椅");

        System.out.println("汽车信息:"+builder.createCar().toString());
    }
}

这个Builder一般写成链式调用,这时Builder类的setter方法需要返回自身,如下:

public abstract class Builder {
    public abstract Builder buildWheel(String wheel);

    public abstract Builder buildSteering(String steering);

    public abstract Builder buildSeat(String seat);

    public abstract Car createCar();
}

public class SixSixSixCarBuilder extends Builder {

    private Car mCar = new Car();

    @Override
    public SixSixSixCarBuilder buildWheel(String wheel) {
        mCar.setmWheel(wheel);
        return this;
    }

    @Override
    public SixSixSixCarBuilder buildSteering(String steering) {
        mCar.setmSteering(steering);
        return this;
    }

    @Override
    public SixSixSixCarBuilder buildSeat(String seat) {
        mCar.setmSeat(seat);
        return this;
    }

    @Override
    public Car createCar() {
        return mCar;
    }
}

调用时:

public class Test{
    public static void main(string[] args){

        Builder builder=new SixSixSixCarBuilder();
        builder.buildWheel("米其林三星轮胎")
                .buildSteering("真皮方向盘")
                .buildSeat("真皮座椅") 
                .createCar();

        System.out.println("汽车信息:" + builder.createCar().toString());
    }
}

Structural Patterns

工厂方法模式

工厂方法模式是应用最广泛的模式,它定义一个用于创建对象的接口,让子类决定实例化哪个类。

Decorator(装饰器模式)

装饰器模式允许我们根据运行时不同的情景动态地为某个对象调用前后添加不同的行为动作。

<?php
class HtmlTemplate {
    // any parent class methods
}

class Template1 extends HtmlTemplate {
    protected $_html;

    public function __construct() {
        $this->_html = "<p>__text__</p>";
    }

    public function set($html) {
        $this->_html = $html;
    }

    public function render() {
        echo $this->_html;
    }
}

class Template2 extends HtmlTemplate {
    protected $_element;

    public function __construct($s) {
        $this->_element = $s;
        $this->set("<h2>" . $this->_html . "</h2>");
    }

    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }
}

class Template3 extends HtmlTemplate {
    protected $_element;

    public function __construct($s) {
        $this->_element = $s;
        $this->set("<u>" . $this->_html . "</u>");
    }

    public function __call($name, $args) {
        $this->_element->$name($args[0]);
    }
}

使用场景

任何需要生成复杂对象的地方都可以使用工厂方法模式。

Adapter(适配器模式)

这种模式允许使用不同的接口重构某个类,可以允许使用不同的调用方式进行调用:

<?php

class SimpleBook {

    private $author;
    private $title;

    function __construct($author_in, $title_in) {
        $this->author = $author_in;
        $this->title  = $title_in;
    }

    function getAuthor() {
        return $this->author;
    }

    function getTitle() {
        return $this->title;
    }
}

class BookAdapter {

    private $book;

    function __construct(SimpleBook $book_in) {
        $this->book = $book_in;
    }
    function getAuthorAndTitle() {
        return $this->book->getTitle().' by '.$this->book->getAuthor();
    }
}

// Usage
$book = new SimpleBook("Gamma, Helm, Johnson, and Vlissides", "Design Patterns");
$bookAdapter = new BookAdapter($book);
echo 'Author and Title: '.$bookAdapter->getAuthorAndTitle();

function echo $line_in) {
  echo $line_in."<br/>";
}

例子

还是组装汽车,具体组装k3、k5属于同一车型的两款车。由于是同一车型所以一条生产线足够。

先明确汽车需要的功能,即汽车抽象基类:

public abstract class QiYaCar {

    public abstract void drive();//汽车可以开

    public abstract void speedUp();//汽车可以加速
}

创建抽象生产线定义类:

public abstract class QiYaFactory {

    /**
     * 
     * @param clzz 具体汽车型号
     * @return 具体的汽车
     */
    public abstract <T extends QiYaCar> T createQiYaCar(Class clzz);
}

创建具体的生产线:

public class QiYaCreateFactory extends QiYaFactory{
    @Override
    public <T extends QiYaCar> T createQiYaCar(Class clzz) {
        QiYaCar car= null;
        try {
            car = (QiYaCar) Class.forName(clzz.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) car;
    }
}

生产具体车型:

public class QiYaK3Car extends QiYaCar{
    @Override
    public void drive() {
        System.out.println("k3启动");
    }

    @Override
    public void speedUp() {
        System.out.println("k3加速");
    }
}

public class QiYaK5Car extends QiYaCar{
    @Override
    public void drive() {
        System.out.println("k5启动");
    }

    @Override
    public void speedUp() {
        System.out.println("k5加速");
    }
}

把上面各个类组装起来就可以形成一条完整的流水线:

public class Client{
    public static void main(string[] args){

        QiYaFactory factory = new QiYaCreateFactory();

        QiYaK3Car k3Car = factory.createQiYaCar(QiYaK3Car.class);
        k3Car.drive();
        k3Car.speedUp();

        QiYaK5Car k5Car = factory.createQiYaCar(QiYaK5Car.class);
        k5Car.drive();
        k5Car.speedUp();
    }
}

Behavioral Patterns

小结

工厂方法模式是一个很好的设计模式,但是从上面例子也可以看出,工厂方法模式也有一定的缺点,比如当添加新的产品时就要编写一个新的产品类,同时还要引用抽象层,导致类的结构复杂化。是否使用工厂方法模式需要根据实际需求决定。


Strategy(策略模式)

测试模式主要为了让客户类能够更好地使用某些算法而不需要知道其具体的实现。

<?php

interface OutputInterface {
    public function load();
}

class SerializedArrayOutput implements OutputInterface {
    public function load() {
        return serialize($arrayOfData);
    }
}

class JsonStringOutput implements OutputInterface {
    public function load() {
        return json_encode($arrayOfData);
    }
}

class ArrayOutput implements OutputInterface {
    public function load() {
        return $arrayOfData;
    }
}

抽象工厂模式

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

Observer(观察者模式)

某个对象可以被设置为是可观察的,只要通过某种方式允许其他对象注册为观察者。每当被观察的对象改变时,会发送信息给观察者。

<?php

interface Observer {
  function onChanged($sender, $args);
}

interface Observable {
  function addObserver($observer);
}

class CustomerList implements Observable {
  private $_observers = array();

  public function addCustomer($name) {
    foreach($this->_observers as $obs)
      $obs->onChanged($this, $name);
  }

  public function addObserver($observer) {
    $this->_observers []= $observer;
  }
}

class CustomerListLogger implements Observer {
  public function onChanged($sender, $args) {
    echo( "'$args' Customer has been added to the list n" );
  }
}

$ul = new UserList();
$ul->addObserver( new CustomerListLogger() );
$ul->addCustomer( "Jack" );

使用场景

一个对象族有相同约束时可以使用抽象工厂模式,如Android、ios都有拨号软件,这个软件属于软件的范畴,但是所在的操作系统不一样,这时候开业考虑使用抽象工厂模式来设计拨号软件。

Chain of responsibility(责任链模式)

这种模式有另一种称呼:控制链模式。它主要由一系列对于某些命令的处理器构成,每个查询会在处理器构成的责任链中传递,在每个交汇点由处理器判断是否需要对它们进行响应与处理。每次的处理程序会在有处理器处理这些请求时暂停。

<?php

interface Command {
    function onCommand($name, $args);
}

class CommandChain {
    private $_commands = array();

    public function addCommand($cmd) {
        $this->_commands[]= $cmd;
    }

    public function runCommand($name, $args) {
        foreach($this->_commands as $cmd) {
            if ($cmd->onCommand($name, $args))
                return;
        }
    }
}

class CustCommand implements Command {
    public function onCommand($name, $args) {
        if ($name != 'addCustomer')
            return false;
        echo("This is CustomerCommand handling 'addCustomer'n");
        return true;
    }
}

class MailCommand implements Command {
    public function onCommand($name, $args) {
        if ($name != 'mail')
            return false;
        echo("This is MailCommand handling 'mail'n");
        return true;
    }
}

$cc = new CommandChain();
$cc->addCommand( new CustCommand());
$cc->addCommand( new MailCommand());
$cc->runCommand('addCustomer', null);
$cc->runCommand('mail', null);

例子

起亚和现代有两条生成线,一个中型车,一个SUV。抽象工厂模式来进行实现这两条生产线。

首先是抽象产品类:

public abstract class BetweenCar{
  public abstract void drive();//汽车可以开

  public abstract void speedUp();//汽车加速

}

public abstract class SUVCar{
   public abstract void drive();//汽车可以开

   public abstract void speedUp();//汽车加速
}

生产具体产品

public class QiYaBetweenCar extends BetweenCar{
    @Override
    public void drive() {
        System.out.println("起亚中型车启动");
    }

    @Override
    public void speedUp() {
        System.out.println("起亚中型车加速");
    }
}

public class XianDaiBetweenCar extends BetweenCar{
    @Override
    public void drive() {
        System.out.println("现代中型车启动");
    }

    @Override
    public void speedUp() {
        System.out.println("现代中型车加速");
    }
}

public class QiYaSUVCar extends SUVCar {
    @Override
    public void drive() {
        System.out.println("起亚SUV启动");
    }

    @Override
    public void speedUp() {
        System.out.println("起亚SUV加速");
    }
}

public class XianDaiSUVCar extends SUVCar {
    @Override
    public void drive() {
        System.out.println("现代SUV启动");
    }

    @Override
    public void speedUp() {
        System.out.println("现代SUV加速");
    }
}

创建生产汽车的抽象工厂里面有两条生产线,即生产中型车和SUV

public abstract class CarFactory {

    public abstract BetweenCar createBetweenCar();

    public abstract SUVCar createSUVCar();

}

定义具体的工厂

public class QiYaCarFactory extends CarFactory{

    @Override
    public BetweenCar createBetweenCar() {
        return new QiYaBetweenCar();
    }

    @Override
    public SUVCar createSUVCar() {
        return new QiYaSUVCar();
    }
}

public class XianDaiCarFactory extends CarFactory {
    @Override
    public BetweenCar createBetweenCar() {
        return new XianDaiBetweenCar();
    }

    @Override
    public SUVCar createSUVCar() {
        return new XianDaiSUVCar();
    }
}

最后客户端调用

public class Client{
    public static void main(string[] args){

        CarFactory qiYaCarFactory = new QiYaCarFactory();

        qiYaCarFactory.createBetweenCar().drive();
        qiYaCarFactory.createBetweenCar().speedUp();

        qiYaCarFactory.createSUVCar().drive();
        qiYaCarFactory.createSUVCar().speedUp();

        CarFactory xianDaiCarFactory = new XianDaiCarFactory();

        xianDaiCarFactory.createBetweenCar().drive();
        xianDaiCarFactory.createBetweenCar().speedUp();

        xianDaiCarFactory.createSUVCar().drive();
        xianDaiCarFactory.createSUVCar().speedUp();
    }
}

小结

抽象工厂模式一个显著的优点是分离接口与实现,客户端使用抽象工厂来创建需要的对象,而客户端不需要知道具体实现是谁,客户端只是面向产品的接口编程,使其从具体的产品视线中解耦,在切换产品类时更加灵活。当然抽象工厂模式不容易扩展新的产品类,因为增加一个产品类就需要修改抽象工厂,则所有具体工厂类都要修改。

发表评论

电子邮件地址不会被公开。 必填项已用*标注