TODO: 设计模式
创造型设计模式
- 简单工厂
- 工厂方法
- 抽象工厂
- 构建器
- 原型
- 单例
结构型设计模式
- 适配器
- 桥梁
- 组合
- 装饰
- 门面
- 享元
- 代理
行为型设计模式
- 责任链
- 命令行
- 迭代器
- 中介者
- 备忘录
- 观察者
- 访问者
- 策略
- 状态
- 模版方法
设计模式
创造型 结构型 行为型
创造型设计模式
简单工厂:
只是为客户端生成一个实例,而不会向客户端公开任何实例化逻辑 工厂时用户创建其他对象的对象,正式工厂是一种函数或方法,它从一些方法调用返回变化的原型或类的对象,这被假定为"新"
程序化示例:
首先,定义一个门界面和实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22interface Door {
public function getWidth(): float;
public function getHeight(): float;
}
clas WoodenDoor implements Door {
protected $width;
protected $height;
public function __construct(float $width, float $height) {
$this -> width = $width;
$this -> height = $height;
}
public function getWidth(): float {
return $this -> width;
}
public function getHeight(): float {
return $this -> height;
}
}我们有我们的门工厂、门,并返回它
1
2
3
4
5class DoorFactory {
public static function makeDoor($width, $height): Door {
return new WoodenDoor($width, $height);
}
}然后它可以用作
1
2
3
4
5
6
7
8// Make me a door of 300 x 300
$door = DoorFactory::makeDoor(300,300);
echo 'Width: ' . $door -> getWidth();
echo 'Height: '. $door -> getHeight();
// Make me a door of 100 x 100
$door2 = DoorFactory::makeDoor(100,100);
用处:当创建一个对象不仅仅是一些分配而且涉及一些逻辑时,将它放在专用工厂中,而不是在任何地方重复相同的代码时有意义的
工厂方法
提供了一种将实例化逻辑委托给子类的方法
处理创建对象的问题,无需指定将要创建的对象的确切类。在接口中指定并由子类实现,或者在基类中实现并可选地由派生类覆盖,而不是通过调用构造函数
程序化示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15interface Interviewer {
public function askQuestions();
}
class Developer implements Interviewer {
public function askQuestions() {
echo 'Factory Design Patterns ';
}
}
class CommunityExecutive implements Interviewer {
public function askQuestions() {
echo 'Asking about community building ';
}
}创造 HiringManager
1
2
3
4
5
6
7
8
9abstract class HiringManager {
// Factory method
abstract protected function makeInterviewer(): Interviewer;
public function takeInterview() {
$interviewer = $this -> makeInterviewer();
$interviewer -> askQuestions();
}
}
任何子类可以延长并提供所需的
1 | class DevelopmentManager extends HiringManager { |
1 | $devManager = new DevelopmentManager(); |
用处:
在类中有一些通用处理但在运行时动态决定所需的子类时用,当客户端不知道他需要什么样子的子类时
- 抽象工厂
将个人 相关\依赖工厂组在一起而不指定其具体类别的工厂
提供了一种封装一组具有共同主题但没有指定具体类的单个工厂的方法
程序化示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15interface Door {
public function getDescription();
}
class WooderDoor implements Door {
public function getDescription() {
echo 'I am a wooden door';
}
}
class IronDoor implements Door {
public function getDescription() {
echo 'I am an iron door';
}
}
为每种门类型都配备一些装配专家
1 | interface DoorFittingExpert { |
有抽象工厂,制作相关对象的家庭,即木门工厂将创建一个木门和木门配件,门专家
1 | interface DoorFactory { |
可用作:
1 | $woodenFactory = new WoodenDoorFactory(); |
木门工厂疯转 各种函数
用法: 当存在互相关联的依赖关系时,涉及非简单的创建逻辑
- 构建器
允许创建不同风格的对象,同时避免构造函数污染,当有几种风格的物体时很有用,或在创建对象时设计很多步骤
目的:找到伸缩构造器反模式的解决方案
程序化示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Burger {
protected $size;
protected $cheese = false;
protected $pepperoni = false;
protected $lettuce = false;
protected $tomato = false;
public function __construct(BurgerBuilder $builder) {
$this -> size = $builder -> size;
$this -> cheese = $builder -> cheese;
$this -> pepperoni = $builder -> pepperoni;
$this -> lettuce = $builder -> lettuce;
$this -> tomato = $builder -> tomato;
}
}
然后有建设者
1 | class BurgerBuilder { |
用法:
1 | $burger = (new BurgerBuilder(14)) |
用处:
当可能存在几种类型的对象并避免构造函数伸缩时,与工厂模式区别在于:当创建时一步过程时,将使用工厂模式,而当创建是多步骤过程时,将使用构造器模式
- 原型
通过克隆基于现有对象创建对象, 允许创建现有对象的副本并进行修改,而不是从头开始创建对象并进行设置
程序化示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class Sheep {
protected $name;
protected $category;
public function __construct(string $name, string $category = 'Mountain Sheep') {
$this -> name = $name;
$this -> category = $category;
}
public function setName(string $name) {
$this -> name = $name;
}
public function getName() {
return $this -> name;
}
public function setCategory(string $category) {
$this -> category = $category;
}
public function getCategory() {
return $this -> category;
}
}
用法:
1 | $original = new Sheep('Hale'); |
可用魔术方法 __clone() 来修改克隆方法
用处: 当需要一个与现有对象类似的对象时,或者与克隆相比,创建的成本会很高
- 单例
确保只创建特定类的一个对象
程序化示例1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22final Class President {
private static $instance;
private function __construct() {
// Hide the constructor
}
public static function getInstance(): President {
if(!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
private function __clone() {
// Disable cloning
}
private function __wakeup() {
// Disable unserialize
}
}
用法:
1 | $president1 = President::getInstance(); |
结构型设计模式
适配器 桥梁 组合 装饰 门面 享元 代理
适配器:
在适配器中包装其他不兼容的对象,以使其与另一个类兼容。 允许将现有类的接口用作另一个接口,通常用于使现有类与其他类一起工作而无需修改其源代码
程序化示例
1 | interface Lion { |
实现任何Lion接口可以进行搜索
1 | class Hunter { |
1 | class Wilddog { |
1 | $wildDog = new WildDog(); |
桥梁模式
优先于集成的组合,实现细节从层次结构推送到具有单独层次结构的另一个对象
程序化示例
1 | interface WebPage { |
1 | interface Theme { |
1 | $darkTheme = new DarkTheme(); |
组合模式
复合模式允许客户以统一的方式处理单个对象
程序化示例
1 | interface Employee { |
1 | class Organization { |
1 | $john = new Developer('John Doe', 12000); |
装饰模式
通过将对象包装在装饰器类的对象中来动态更改对象在运动时的行为
程序化示例
1 | interface Coffee { |
添加组件
1 | class MilkCoffee implements Coffee { |
1 | $someCoffee = new SimpleCoffee(); |
门面模式
Facade 模式为复杂的子系统提供了简化的界面
外观是一个对象,它为更大的代码提供了简化的接口,如类库
程序化示例
1 | class Computer { |
1 | class ComputerFacade { |
1 | $computer = new ComputerFacade(new Computer()); |
享元模式
通过尽可能多地与类似对象共享来最小化内存使用或计算开销
程序示例
1 | class KarakTea {} |
1 | class TeaShop { |
1 | $teaMaker = new TeaMaker(); |
代理模式
类表示另一个类的功能
程序化示例
1 | interface Door { |
1 | class SecuredDoor { |
用法:
1 | $door = new SecureDoor(new LabDoor()); |
行为型设计模式
责任链 命令行 迭代器 中介者 备忘录 观察者 访问者 策略 状态 模板
责任链
构建一系列对象,请求从一端进入并继续从一个对象到另一个对象,直到找到合适的处理程序
程序示例
1 | abstract class Account { |
1 | $bank = new Bank(100); |
命令行
将操作封装在对象中,提供将客户与接收器分离的方法. 对象用于封装执行动作或稍后触发事件所需的所有信息,此信息包括方法名称,拥有该方法的对象以及方法参数的值。
程序化示例
1 | class Bulb { |
1 | interface Command { |
1 | class RemoteControl { |
1 | $bulb = new Bulb(); |
迭代器
提供了一种访问对象元素而不是暴露底层表示的方法
用于遍历容器并访问容器的元素,将算法与容器分离,因算法是特定于容器,so 不能解耦
程序化示例
1 | class RadioStation { |
1 | use Countable; |
1 | $stationList = new StationList(); |
中介者
添加第三方对象控制两个对象之间的交互,减少彼此通信的类之间的耦合,不需要了解彼此的实施。 中介模式定义了一个对象,该对象封装了一组对象的交互方式,可以改变程序的运行行为。
程序化示例
1 | interface ChatRoomMediator { |
1 | class User { |
1 | $mediator = new ChatRoom(); |