设计模式是什么?

设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。

所以设计模式不是固定的,也不是一成不变的,会根据实际项目的演变而演变。也不是说某些大牛制定的设计师模式是什么样子的,而是在实际项目中,为解决普遍存在的问题而总结的经验。

常见设计模式

创建型模式

  • 抽象工厂
  • 构造器
  • 工厂方法
  • 原型
  • 单例模式

结构型模式

  • 适配器
  • 桥接
  • 组合
  • 装饰
  • 外观
  • 享元
  • 代理

行为型模式

  • 职责链
  • 命令
  • 翻译器
  • 迭代器
  • 中介者
  • 回忆
  • 观察者
  • 状态机
  • 策略
  • 模板方法
  • 参观者

详解

单例模式

单例的核心思想是什么?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php

class TestSingleton {
    private static $instance;

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

        return static::$instance = new static();
    }

    private function __construct(){}

    private function __clone(){}

    private function __sleep(){}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Singleton {
    private static Singleton instance = null;

    private Singleton() {

    }

    public static Singleton getInstance() {
        if(instance == null){
            synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

适配器

是什么,怎么用,什么场景用。

iPhone 手机, Android micro-usb, Android type-c 手机。分别需要 lighting接口, micro-usb, type-c 各种接口。

现在我有一个 usb 充电头, 一个 micro-usb 充电线,如果想给手机充电,要判断设备型号,然后使用适配器来搞定。

 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
<?php

interface LightingChargingIf 
{
    function chargeWithLighting();
}

interface TypeCIf 
{
    function chargeWithTypeC();
}


class AppleCharger implements LightingChargingIf 
{
    public function chargeWithLighting() 
    {
        echo "charge use lighting.", PHP_EOL;
    }
}

class AndroidChargerUseTypeC implements TypeCIf 
{
    public function chargeWithTypeC()
    {
        echo "charge use type-c.", PHP_EOL;
    }
}

abstract class Phone 
{
    abstract function charge();
}

class Mi8 extends Phone
{
    /**
     * @var TypeCIf
     */
    private $charger;

    public function __construct(TypeCIf $charger)
    {
        $this->charger = $charger;
    }

    public function charge()
    {
        $this->charger->chargeWithTypeC();
    }
}

class Iphone8 extends Phone
{
    private $charger;

    public function __construct(LightingChargingIf $charger)
    {
        $this->charger = $charger;
    }

    public function charge()
    {
        $this->charger->chargeWithLighting();
    }
}

class TypeCToLightingAdapter implements LightingChargingIf
{
    private $charger;

    public function __construct(TypeCIf $charger)
    {
        $this->charger = $charger;
    }

    public function chargeWithLighting() 
    {
        $this->charger->chargeWithTypeC();
        echo "charge use lighting with type-c adapter.", PHP_EOL;
    }
}


$appleCharger = new AppleCharger();
$typeCCharger = new AndroidChargerUseTypeC();

echo str_repeat('-', 100), PHP_EOL;
$myPhone = new Iphone8($appleCharger);
$myPhone->charge();
echo str_repeat('-', 100), PHP_EOL;
$myPhone = new Iphone8(new TypeCToLightingAdapter($typeCCharger));
$myPhone->charge();

观察者模式

  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
<?php

abstract class BaseSubject implements SplSubject
{
    private $objectList;

    public function __construct()
    {
        $this->objectList = new SplObjectStorage();
    }

    public function attach(SplObserver $observer): void 
    {
        $this->objectList->attach($observer);
    }
    public function detach (SplObserver $observer): void
    {
        $this->objectList->detach($observer);
    }
    public function notify(): void
    {
        foreach ($this->objectList as $observer) {
            $observer->update($this);
        }
    }
}

class UserRegisterSubject extends BaseSubject
{
    public $user;

    public function __construct(User $user)
    {
        $this->objectList = new SplObjectStorage();
        $this->user = $user;
    }

    public function attach(SplObserver $observer): void 
    {
        $this->objectList->attach($observer);
    }
    public function detach (SplObserver $observer): void
    {
        $this->objectList->detach($observer);
    }
    public function notify(): void
    {
        foreach ($this->objectList as $observer) {
            $observer->update($this);
        }
    }
}

class UserLogoutSubject extends BaseSubject
{
    private $objectList;

    public $user;

    public function __construct(User $user)
    {
        $this->objectList = new SplObjectStorage();
        $this->user = $user;
    }

    public function attach(SplObserver $observer): void 
    {
        $this->objectList->attach($observer);
    }
    public function detach (SplObserver $observer): void
    {
        $this->objectList->detach($observer);
    }
    public function notify(): void
    {
        foreach ($this->objectList as $observer) {
            $observer->update($this);
        }
    }
}

class SendRegisterObserver implements SplObserver
{
    public function update(SplSubject $subject)
    {
        echo sprintf("[sms] Hi guys, register success. id:%s, name: %s\n", $subject->user->id, $subject->user->name);
    }
}

class SendEmailObserver implements SplObserver
{
    public function update(SplSubject $subject)
    {
        echo sprintf("[email] Hi guys, register success. id:%s, name: %s\n", $subject->user->id, $subject->user->name);
    }
}

class User 
{
    public $id;
    public $name;

    public function __construct(int $id, string $name)
    {
        $this->id = $id;
        $this->name = $name;
    }
}


$user = new User(110, '抓人');
$user2 = new User(120, '救人');

# 注册两个人
$subject = new UserRegisterSubject($user);
$subject2 = new UserRegisterSubject($user2);

$smsObserver = new SendRegisterObserver();
$emailObserver = new SendEmailObserver();

// 110 发邮件 + 发短信
$subject->attach($smsObserver);
$subject->attach($emailObserver);

// 120 发短信
$subject2->attach($smsObserver);

# if 110 注册, 触发
$subject->notify();
# endif 

# if 120 注册, 触发
$subject2->notify();
# endif

参考资料