设计模式

设计模式

并非所有开发语言都支持所有设计模式,有的开发语言只支持个别设计模式。

创建型模式(Creational)

关注对象的实例化过程,包括了如何实例化对象、隐藏对象的创建细节等。

单例模式(Singleton Pattern)

确保一个类只有一个实例,并提供该实例的全局访问点。

数据库类设计,只连接一次数据库,防止打开多个数据库连接

使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。

私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。

 1class Single {
 2    private $name;//声明一个私有的实例变量
 3    private function __construct(){//声明私有构造方法为了防止外部代码使用new来创建对象。
 4    
 5    }
 6
 7    static public $instance;//声明一个静态变量(保存在类中唯一的一个实例)
 8    static public function getinstance(){//声明一个getinstance()静态方法,用于检测是否有实例对象
 9        if(!self::$instance) self::$instance = new self();
10        return self::$instance;
11    }
12
13    public function setname($n){ $this->name = $n; }
14    public function getname(){ return $this->name; }
15}
16
17$oa = Single::getinstance();
18$ob = Single::getinstance();
19$oa->setname('hello php world');
20$ob->setname('good morning php');
21echo $oa->getname();//good morning php
22echo $ob->getname();//good morning php

简单工厂

在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。

简单工厂又叫静态工厂方法模式,简单工厂模式是通过一个静态方法创建对象的。

违反开闭原则(对于扩展是开放的,对于修改是关闭的)

新增时需要改动原有类文件,在里面新增方法或判断。

调用时用同一个对象,但用的方法不一样,或传进去的参数不一样。如:

 1<?php
 2SimpleFactoty::creatA();
 3SimpleFactoty::creatB();
 4SimpleFactoty::creatC();
 5
 6// or
 7
 8SimpleFactoty::creat("A");
 9SimpleFactoty::creat("B");
10SimpleFactoty::creat("C");
 1<?php
 2interface  people
 3{
 4    function marry();
 5}
 6
 7class man implements people
 8{
 9    function marry()
10    {
11        echo '送玫瑰,送戒指!';
12    }
13}
14
15class women implements people
16{
17    function marry()
18    {
19        echo '穿婚纱!';
20    }
21}
22
23class SimpleFactoty
24{
25    // 简单工厂里的静态方法
26    static function createMan()
27    {
28        return new     man;
29    }
30
31    static function createWomen()
32    {
33        return new     women;
34    }
35
36}
37
38SimpleFactoty::createMan()->marry();
39// 送玫瑰,送戒指!
40SimpleFactoty::createWomen()->marry();
41// 穿婚纱!

简单工厂: 调用时SimpleFactoty一样,createMan方法不一样 工厂方法: 调用时SimpleFactoty不一样,createMan方法一样

工厂方法

定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。

遵循开闭原则。

新增方法不用改原有类文件,新增文件后继承上游类或接口即可调用。

调用时,对象不一样,但调用方法和返回类型皆为一致。

如:

1<?php
2FactoryA::create();
3FactoryB::create();
4FactoryC::create();
5?>

使用场景:

  • 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
  • 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
  • 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

在工厂方法中,由子类来创建对象。

 1<?php
 2interface  people
 3{
 4    function marry();
 5}
 6
 7class man implements people
 8{
 9    function marry()
10    {
11        echo '送玫瑰,送戒指!';
12    }
13}
14
15class women implements people
16{
17    function marry()
18    {
19        echo '穿婚纱!';
20    }
21}
22
23interface  createMan
24{  // 注意了,这里是简单工厂本质区别所在,将对象的创建抽象成一个接口。
25    function create();
26}
27
28class FactoryMan implements createMan
29{
30    function create()
31    {
32        return new man;
33    }
34}
35
36class FactoryWomen implements createMan
37{
38    function create()
39    {
40        return new women;
41    }
42}
43
44FactoryMan::create()->marry();
45//送玫瑰,送戒指!
46FactoryWomen::create()->marry();
47//穿婚纱!
48?>

与简单工厂不同的是前面的FactoryMan对象是变化的,create方法是固定的。

抽象工厂

提供一个接口,用于创建 相关的对象家族 。

抽象工厂模式是工厂模式的一个扩展,如果抽象工厂只有一个产品体系就会退化成工厂模式。属于简单工厂和工厂模式的合体。

违反开闭原则

新增时 可能 需要改动原有类文件,在里面新增方法或判断。同样要继承上游类或接口。

调用时,对象和调用方法都可不一样。

如:

1<?php
2FactoryA::create();
3FactoryB::change();
4FactoryC::change();
5FactoryD::delete();
6?>

体现出了面向接口编程的思想,其实就是用工厂方法生产具有多维度变化的产品类。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 工厂里加代码,又要在具体的实现加代码

 1<?php
 2interface  people
 3{
 4    function marry();
 5}
 6
 7class Oman implements people
 8{
 9    function marry()
10    {
11        echo '美女,我送你玫瑰和戒指!';
12    }
13}
14
15class Iman implements people
16{
17    function marry()
18    {
19        echo '我偷偷喜欢你';
20    }
21}
22
23class Owomen implements people
24{
25    function marry()
26    {
27        echo '我要穿婚纱!';
28    }
29}
30
31class Iwomen implements people
32{
33    function marry()
34    {
35        echo '我好害羞哦!!';
36    }
37}
38
39interface  createMan
40{  // 注意了,这里是本质区别所在,将对象的创建抽象成一个接口。
41    function createOpen(); //分为 内敛的和外向的
42
43    function createIntro(); //内向
44}
45
46class FactoryMan implements createMan
47{
48    function createOpen()
49    {
50        return new  Oman;
51    }
52
53    function createIntro()
54    {
55        return new Iman;
56    }
57}
58
59class FactoryWomen implements createMan
60{
61    function createOpen()
62    {
63        return new  Owomen;
64    }
65
66    function createIntro()
67    {
68        return new Iwomen;
69    }
70}
71
72FactoryMan::createOpen()->marry();  //美女,我送你玫瑰和戒指!
73FactoryMan::createIntro()->marry(); //我偷偷喜欢你
74
75FactoryWomen::createOpen()->marry();    //我要穿婚纱!
76FactoryWomen::createIntro()->marry();   //我好害羞哦!!
77?>

生成器

封装一个对象的构造过程,并允许按步骤构造。

原型模式

使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。

行为型

责任链

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

命令

将命令封装成对象中,具有以下作用:

  • 使用命令来参数化其它对象
  • 将命令放入队列中进行排队
  • 将命令的操作记录到日志中
  • 支持可撤销的操作

解释器

为语言创建解释器,通常由语言的语法和语法分析来定义。

迭代器

提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。

中介者

集中相关对象之间复杂的沟通和控制方式。

备忘录

在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。

观察者

定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。

主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。

状态

允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。

策略

定义一系列算法,封装每个算法,并使它们可以互换。

策略模式可以让算法独立于使用它的客户端。

模板方法

定义算法框架,并将一些步骤的实现延迟到子类。

通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。

访问者

为一个对象结构(比如组合结构)增加新能力。

空对象

使用什么都不做

的空对象来代替 NULL。

一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。

结构型

适配器

把一个类接口转换成另一个用户需要的接口。

桥接

将抽象与实现分离开来,使它们可以独立变化。

组合

将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。

装饰

为对象动态添加功能。

外观

提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。

享元

利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。

代理

控制对其它对象的访问。

浏览量:加载中... 评论数:加载中...