`
hongtoushizi
  • 浏览: 359102 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

php设计模式(一):简介及创建型模式

阅读更多

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。

一、设计模式简介首先我们来认识一下什么是设计模式:设计模式是一套被反复使用、容易被他人理解的、可靠的代码设计经验的总结。设计模式不是Java的专利,我们用面向对象的方法在PHP里也能很好的使用23种设计模式。那么我们常说的架构、框架和设计模式有什么关系呢?架构是一套体系结构,是项目的整体解决方案;框架是可供复用的半成品软件,是具体程序代码。架构一般会涉及到采用什么样的框架来加速和优化某部分问题的解决,而好的框架代码里合理使用了很多设计模式。 二、提炼设计模式的几个原则:开闭原则:模块应对扩展开放,而对修改关闭。里氏代换原则:如果调用的是父类的话,那么换成子类也完全可以运行。依赖倒转原则:抽象不依赖细节,面向接口编程,传递参数尽量引用层次高的类。接口隔离原则:每一个接口只负责一种角色。合成/聚合复用原则:要尽量使用合成/聚合,不要滥用继承。三、设计模式的功用?                     设计模式能解决替换杂乱无章的代码,形成良好的代码风格代码易读,工程师们都能很容易理解增加新功能时不用修改接口,可扩展性强稳定性好,一般不会出现未知的问题                   设计模式不能解决:设计模式是用来组织你的代码的模板,而不是直接调用的库;设计模式并非最高效,但是代码的可读性和可维护性更重要;不要一味追求并套用设计模式,重构时多考虑;  四、设计模式分类   1、创建型模式:单例模式、工厂模式(简单工厂、工厂方法、抽象工厂)、创建者模式、原型模式。   2、结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。      3、行为型模式:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。 五、创建型设计模式1、单例模式目的:保证一个类仅有一个实例,并提供一个访问它的全局访问点。应用场景:数据库连接、缓存操作、分布式存储。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
/**
 * 优才网公开课示例代码
 *
 * 单例模式
 *
 * @author 优才网全栈工程师教研组
 */
     
class DbConn
{
     
       private static $_instance = null;
       protected static $_counter = 0;
       protected $_db;
          
       //私有化构造函数,不允许外部创建实例
       private function __construct()
       {
              self::$_counter += 1;
       }
     
       public function getInstance()
       {
              if (self::$_instance == null)
              {
                     self::$_instance = new DbConn();
              }
              return self::$_instance;
       }
     
       public function connect()
       {
              echo "connected: ".(self::$_counter)."n";
              return $this->_db;
       }
     
}
     
/*
 * 不使用单例模式时,删除构造函数的private后再测试,第二次调用构造函数后,_counter变成2
*/
// $conn = new DbConn();
// $conn->connect();
// $conn = new DbConn();
// $conn->connect();
     
//使用单例模式后不能直接new对象,必须调用getInstance获取
$conn = DbConn::getInstance();
$db = $conn->connect();
//第二次调用是同一个实例,_counter还是1
$conn = DbConn::getInstance();
$db = $conn->connect();
?>


特 别说明:这里getInstance里有if判断然后再生成对象,在多线程语言里是会有并发问题的。例如java的解决方案有二个,给方法加上 synchronized关键词变成同步,或者把_instanc的初始化提前放到类成员变量定义时,但是这2种方式php都不支持。不过因为php不支 持多线程所以不需要考虑这个问题了。2、工厂模式实现:定义一个用于创建对象的接口,让子类决定实例化哪一个类。应用场景:众多子类并且会扩充、创建方法比较复杂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php
/**
 * 优才网公开课示例代码
 *
 * 工厂模式
 *
 * @author 优才网全栈工程师教研组
 */
     
//抽象产品
interface Person {
    public function getName(); 
}
//具体产品实现
class Teacher implements Person {
    function getName() {
        return "老师n";
    }
}
class Student implements Person {
    function getName() {
        return "学生n";
    }
}
     
//简单工厂
class SimpleFactory {
       public static function getPerson($type) {
              $person = null;
              if ($type == 'teacher') {
                     $person = new Teacher();
              } elseif ($type == 'student') {
                     $person = new Student();
              }
              return $person;
       }
}
     
//简单工厂调用
class SimpleClient {
       function main() {
              // 如果不用工厂模式,则需要提前指定具体类
              // $person = new Teacher();
              // echo $person->getName();
              // $person = new Student();
              // echo $person->getName();
     
              // 用工厂模式,则不需要知道对象由什么类产生,交给工厂去决定
              $person = SimpleFactory::getPerson('teacher');
              echo $person->getName();
              $person = SimpleFactory::getPerson('student');
              echo $person->getName();
       }
}
     
     
//工厂方法
interface CommFactory {
    public function getPerson();
}
//具体工厂实现
class StudentFactory implements CommFactory {
    function getPerson(){
        return new Student();
    }
}
class TeacherFactory implements CommFactory {
    function getPerson() {
        return new Teacher();
    }
}
     
//工厂方法调用
class CommClient {
    static function main() {
           $factory = new TeacherFactory();
           echo $factory->getPerson()->getName();
           $factory = new StudentFactory();
           echo $factory->getPerson()->getName();
    }
}
     
     
     
//抽象工厂模式另一条产品线
interface Grade {
       function getYear();
}
//另一条产品线的具体产品
class Grade1 implements Grade {
       public function getYear() {
              return '2003级';
       }
}
class Grade2 implements Grade {
       public function getYear() {
              return '2004级';
       }
}
//抽象工厂
interface AbstractFactory {
       function getPerson();
       function getGrade();
}
//具体工厂可以产生每个产品线的产品
class Grade1TeacherFactory implements AbstractFactory {
       public function getPerson() {
              return new Teacher();
       }
       public function getGrade() {
              return new Grade1();
       }
}
class Grade1StudentFactory implements AbstractFactory {
       public function getPerson() {
              return new Student();
       }
       public function getGrade() {
              return new Grade1();
       }
}
class Grade2TeacherFactory implements AbstractFactory {
       public function getPerson() {
              return new Teacher();
       }
       public function getGrade() {
              return new Grade2();
       }
}
//抽象工厂调用
class FactoryClient {
       function printInfo($factory) {
              echo $factory->getGrade()->getYear().$factory->getPerson()->getName();
       }
       function main() {
              $client = new FactoryClient();
              $factory = new Grade1TeacherFactory();
              $client->printInfo($factory);
              $factory = new Grade1StudentFactory();
              $client->printInfo($factory);
              $factory = new Grade2TeacherFactory();
              $client->printInfo($factory);
       }
}
     
     
//简单工厂
//SimpleClient::main();
//工厂方法
//CommClient::main();
//抽象工厂
FactoryClient::main();
     
?>


三 种工厂的区别是,抽象工厂由多条产品线,而工厂方法只有一条产品线,是抽象工厂的简化。而工厂方法和简单工厂相对,大家初看起来好像工厂方法增加了许多代 码但是实现的功能和简单工厂一样。但本质是,简单工厂并未严格遵循设计模式的开闭原则,当需要增加新产品时也需要修改工厂代码。但是工厂方法则严格遵守开 闭原则,模式只负责抽象工厂接口,具体工厂交给客户去扩展。在分工时,核心工程师负责抽象工厂和抽象产品的定义,业务工程师负责具体工厂和具体产品的实 现。只要抽象层设计的好,框架就是非常稳定的。 3、创建者模式在创建者模式中,客户端不再负责对象的创建与组装,而是把这个对象创建的责任交给其具体的创建者类,把组装的责任交给组装类,客户端支付对对象的调用,从而明确了各个类的职责。应用场景:创建非常复杂,分步骤组装起来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?php
/**
 * 优才网公开课示例代码
 *
 * 创建者模式
 *
 * @author 优才网全栈工程师教研组
 */
     
//购物车
class ShoppingCart {
       //选中的商品
    private $_goods = array();
    //使用的优惠券
    private $_tickets = array();
     
       public function addGoods($goods) {
              $this->_goods[] = $goods;
       }
       
    public function addTicket($ticket) {
           $this->_tickets[] = $ticket;
    }
     
    public function printInfo() {
           printf("goods:%s, tickets:%sn", implode(',', $this->_goods), implode(',', $this->_tickets));
    }
}
     
//假如我们要还原购物车的东西,比如用户关闭浏览器后再打开时会根据cookie还原
$data = array(
       'goods' => array('衣服', '鞋子'),
       'tickets' => array('减10'),
);
     
//如果不使用创建者模式,则需要业务类里一步步还原购物车
// $cart = new ShoppingCart();
// foreach ($data['goods'] as $goods) {
//   $cart->addGoods($goods);
// }
// foreach ($data['tickets'] as $ticket) {
//   $cart->addTicket($ticket);
// }
// $cart->printInfo();
// exit;
     
     
//我们提供创建者类来封装购物车的数据组装
class CardBuilder {
       private $_card;
       function __construct($card) {
              $this->_card = $card;
       }
       function build($data) {
              foreach ($data['goods'] as $goods) {
                     $this->_card->addGoods($goods);
              }
              foreach ($data['tickets'] as $ticket) {
                     $this->_card->addTicket($ticket);
              }
       }
       function getCrad() {
              return $this->_card;
       }
}
     
$cart = new ShoppingCart();
$builder = new CardBuilder($cart);
$builder->build($data);
echo "after builder:n";
$cart->printInfo();
     
?>


可以看出,使用创建者模式对内部数据复杂的对象封装数据组装过程后,对外接口就会非常简单和规范,增加修改新数据项也不会对外部造成任何影响。3、 原型模式用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。应用场景: 类的资源非常多、性能和安全要求,一般和工厂方法结合使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?php
/**
 * 优才网公开课示例代码
 *
 * 原型模式
 *
 * @author 优才网全栈工程师教研组
 */
     
//声明一个克隆自身的接口
interface Prototype {
    function copy(); 
}   
     
//产品要实现克隆自身的操作
class Student implements Prototype {
       //简单起见,这里没有使用get set
    public $school;
    public $major;
       public $name;
     
       public function __construct($school, $major, $name) {
              $this->school = $school;
              $this->major = $major;
              $this->name = $name;
       }
     
       public function printInfo() {
              printf("%s,%s,%sn", $this->school, $this->major, $this->name);
       }
       
    public function copy() {
           return clone $this;
    }
}
     
$stu1 = new Student('清华大学', '计算机', '张三');
$stu1->printInfo();
     
$stu2 = $stu1->copy();
$stu2->name = '李四';
$stu2->printInfo();
     
?>


这里可以看到,如果类的成员变量非常多,如果由外部创建多个新对象再一个个赋值,则效率不高代码冗余也容易出错,通过原型拷贝复制自身再进行微小修改就是另一个新对象了。 设计模式的第一部分,创建型模式就总结完了。下面还有两部分结构型设计模式和行为型设计模式稍后继续

 

转载自:http://www.ucai.cn/blogdetail/7020?mid=1

分享到:
评论

相关推荐

    Learning+PHP设计模式

    通过学习如何在代码中使用设计模式,可以更高效...第5部分 MySQL和PHP设计模式 第11章 通用类负责连接,代理模式保证安全 第12章 策略设计模式的灵活性 第13章 职责链设计模式 第14章 利用观察者模式构建多设备CMS

    PhpPatterns:php设计模式

    创建型模式实例 单例模式 :check_mark_button: 工厂模式 :check_mark_button: 抽象工厂模式 :check_mark_button: 简单工厂模式 :check_mark_button: 静态工厂模式 :check_mark_button: 原型模式 建造者模式 结构型...

    PHP设计模式(四)原型模式Prototype实例详解【创建型】

    我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象而不需要提供专门的new()操作就可以快速完成对象的创建,这无疑是一种非常...

    PHP设计模式(一)工厂模式Factory实例详解【创建型】

    本文实例讲述了PHP设计模式(一)工厂模式Factory。分享给大家供大家参考,具体如下: 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new...

    PHP设计模式之工厂方法设计模式实例分析

    本文实例讲述了PHP设计模式之工厂方法设计模式。分享给大家供大家参考,具体如下: 一、什么是工厂方法模式 作为一种创建型设计模式,工厂方法模式就是要创建“某种东西”。对于工厂方法,要创建的“东西”是一个...

    PHP设计模式之工厂模式定义与用法详解

    本文实例讲述了PHP设计模式之工厂模式定义与用法。分享给大家供大家参考,具体如下: 工厂模式(Factory Design Pattern)作为一种创建型设计模式, 遵循了开放-封闭原则, 对修改封闭, 对扩展开放. 工厂方法(Factory ...

    PHP设计模式(三)建造者模式Builder实例详解【创建型】

    本文实例讲述了PHP设计模式:建造者模式Builder。分享给大家供大家参考,具体如下: 1. 概述  在软件开发的过程中,当遇到一个“复杂的对象”的创建工作,该对象由一定各个部分的子对象用一定的算法构成,由于需求...

    PHP中的几种设计模式1

    (1)简单工厂模式简单工厂模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式 (2) 工厂方法模式此模式中,通过定义一

    php设计模式之职责链模式定义与用法经典示例

    本文实例讲述了php设计模式之职责链模式定义与用法。分享给大家供大家参考,具体如下: &lt;?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链...

    php设计模式 State (状态模式)

    状态模式属于对象创建型模式,其意图是允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了他的类。比较常见的例子是在一个表示网络连接的类TCPConnection,一个TCPConnection对象的状态处于若干...

    PHP设计模式之简单工厂和工厂模式实例分析

    工厂模式是创建型模式的一种,分为简单工厂模式,工厂模式,抽象工厂模式,简单工厂可以称之为工厂模式的一个特例 先用一段简单的代码说明一下,现在假设我们是顾客,需要苹果味饮料和香蕉味饮料 &lt;?php class ...

    php设计模式之装饰模式应用案例详解

    本文实例讲述了php设计模式之装饰模式。分享给大家供大家参考,具体如下: 介绍 装饰者模式(Decorator Pattern)允许你向一个现有的对象添加新的功能,同时又不改变其结构。 这种类型的设计模式属于结构型模式,它...

    浅析php单例模式

    本系列文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式之单例模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设计经验的总结。 ...

    PHP 工厂方法模式.pdf

    在软件工程中,创建型设计模式是处理&lt;对象创建机制&gt;的设计模式,试图根据实际情况,选择适当的方式创建对象。因为对象的创建时的状态,可能导致设计问题,或者提升设计的复杂度。创建型设计模式通过 以某种方式控制...

    浅析php工厂模式

    本系列文章来总结一下设计模式在PHP中的应用,这是第二篇创建型模式之工厂模式。 设计模式的一般介绍在第一篇文章讲了,这里就不重复。 工厂模式 实现:定义一个用于创建对象的接口,让子类决定实例化哪一个类。 ...

    PHP设计模式之工厂模式详解

    在开发大型系统时,往往会出现这样一种情况: 我有一部分基础数据,是类classA是从数据库A读取出来的,其他很多的...工厂模式是一种类,建立了一个工厂来根据所需来创建对象,这种方式在多态性编程中是很重要的,允许动

    PHP中单例模式与工厂模式详解

    单例模式是指整个应用中类只有一个对象实例的设计模式。 单例模式的特点 一个类在整个应用中只有一个实例 类必须自行创建这个实例 必须自行向整个系统提供这个实例 php中使用单例模式的原因 我用php大部分操作都是和...

Global site tag (gtag.js) - Google Analytics