含义描述
应用程序中最多只有该类的一个实例存在
应用场景
常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。
代码示例
class Singleton {
private static $instance; // 定义一个私有的静态变量保存类的实例
private function __construct() {
} // 将构造函数设为私有,防止外部直接创建对象
public static function getInstance() {
if (!self::$instance) {
// 如果没有实例化则进行实例化操作
self::$instance = new self();
}
return self::$instance; // 返回已经实例化好的对象
}
}
// 调用单例模式获取实例
$obj1 = Singleton::getInstance();
$obj2 = Singleton::getInstance();
var_dump($obj1 === $obj2); // true,两次获取到的都是同一个实例
含义描述
工厂设计模式常用于根据输入参数的不同或者应用程序配置的不同来创建一种专门用来实例化并返回其对应的类的实例
应用场景
1.后台数据导出:比如可导出文件类型有excel、csv、xml等,同样都是实现导出功能,但是要实例化的类是不同的,实现逻辑也不相同;
2.支付系统:根据用户选择的支付方式实例化不同的支付类,比如积分、微信、支付宝等支付
3.缓存功能:一般有文件缓存、session、cookie等,他们的实例也是不同的。
代码示例
<?php
// 定义接口,定义所有对象的通用方法
interface ShapeInterface
{
public function draw();
}
// 实现接口的具体类,画一个圆形
class Circle implements ShapeInterface
{
public function draw()
{
echo "Drawing a circle.\n";
}
}
// 实现接口的具体类,画一个长方形
class Rectangle implements ShapeInterface
{
public function draw()
{
echo "Drawing a rectangle.\n";
}
}
// 工厂类
class ShapeFactory
{
// 根据传入的形状类型生成对应的对象
public static function createShape($shapeType)
{
if ($shapeType == 'circle') {
return new Circle();
} elseif ($shapeType == 'rectangle') {
return new Rectangle();
} else {
throw new Exception("Invalid shape type: " . $shapeType);
}
}
}
// 使用工厂类生成对象并调用方法
try {
$circle = ShapeFactory::createShape('circle');
$circle->draw();
$rectangle = ShapeFactory::createShape('rectangle');
$rectangle->draw();
// 尝试创建无效的形状类型
$invalidShape = ShapeFactory::createShape('triangle');
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
输出结果:
Drawing a circle.
Drawing a rectangle.
Error: Invalid shape type: triangle
在这个示例中,我们定义了一个ShapeInterface接口,它包含了一个draw()方法,用于绘制形状。然后,我们创建了两个实现该接口的具体类Circle和Rectangle,它们分别实现了draw()方法来绘制圆形和矩形。
接下来,我们创建了一个ShapeFactory工厂类,它包含一个静态方法createShape(),该方法根据传入的形状类型(字符串)生成相应的对象实例。在createShape()方法中,我们根据传入的形状类型使用条件语句创建对应的对象,并返回该对象。如果传入的形状类型无效,我们将抛出一个异常。
最后,我们使用ShapeFactory类来生成圆形和矩形的对象,并调用它们的draw()方法来绘制形状。同时,我们也尝试创建一个无效的形状类型(三角形),以演示异常处理机制。
含义描述
策略设计模式是一种行为设计模式,它允许你在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改应用场景
应用场景
代码示例
//我们将以一个简单的日志记录系统为例,其中我们可以选择不同的日志策略来记录信息。
//首先,我们定义一个日志策略接口:
<?php
interface LoggingStrategy {
public function log(string $message);
}
//然后,我们实现几种不同的日志策略,例如控制台日志、文件日志和数据库日志:
<?php
class ConsoleLog implements LoggingStrategy {
public function log(string $message) {
echo "Console: " . $message . PHP_EOL;
}
}
class FileLog implements LoggingStrategy {
private $file;
public function __construct(string $file) {
$this->file = $file;
}
public function log(string $message) {
file_put_contents($this->file, "File: " . $message . PHP_EOL, FILE_APPEND);
}
}
class DatabaseLog implements LoggingStrategy {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function log(string $message) {
$stmt = $this->pdo->prepare("INSERT INTO logs (message) VALUES (?)");
$stmt->execute([$message]);
}
}
//接下来,我们创建一个Logger类,该类使用策略模式来记录日志:
<?php
class Logger {
private $strategy;
public function __construct(LoggingStrategy $strategy) {
$this->strategy = $strategy;
}
public function setStrategy(LoggingStrategy $strategy) {
$this->strategy = $strategy;
}
public function log(string $message) {
$this->strategy->log($message);
}
}
//最后,我们在主程序中使用Logger类:
<?php
// 创建一个PDO实例用于数据库连接(这里仅作示例,实际使用时需要配置数据库连接参数)
$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'username', 'password');
// 创建不同的日志策略实例
$consoleLog = new ConsoleLog();
$fileLog = new FileLog('path/to/logfile.log');
$databaseLog = new DatabaseLog($pdo);
// 创建一个Logger实例,并设置初始的日志策略为控制台日志
$logger = new Logger($consoleLog);
$logger->log("This is a console log message.");
// 更改日志策略为文件日志
$logger->setStrategy($fileLog);
$logger->log("This is a file log message.");
// 更改日志策略为数据库日志
$logger->setStrategy($databaseLog);
$logger->log("This is a database log message.");
在这个例子中,Logger类是一个上下文类,它使用LoggingStrategy接口来定义日志记录的行为。通过setStrategy方法,我们可以动态地更改日志记录的策略,从而在不同的场景下使用不同的日志记录方式。这样,如果我们想要添加新的日志策略,只需要实现LoggingStrategy接口,并在Logger中使用它即可,而不需要修改Logger类的代码。
含义描述
观察者模式是一种软件设计模式,属于对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用场景
代码示例
在 PHP 中实现观察者模式,可以定义一个 Subject 类和一个 Observer 接口。Subject 类维护一个观察者列表,并提供添加、删除和通知观察者的方法。Observer 接口定义了观察者需要实现的方法。
下面是一个简单的示例代码,展示了如何在 PHP 中实现观察者模式:
<?php
// Observer 接口
interface Observer {
public function update(Subject $subject);
}
// ConcreteObserver 类
class ConcreteObserver implements Observer {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function update(Subject $subject) {
echo "Observer {
$this->name} received update: {
$subject->getState()}\n";
}
}
// Subject 类
class Subject {
private $observers = [];
private $state;
public function attach(Observer $observer) {
$this->observers[] = $observer;
}
public function detach(Observer $observer) {
$key = array_search($observer, $this->observers);
if ($key !== false) {
unset($this->observers[$key]);
}
}
public function notify() {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
public function setState($state) {
$this->state = $state;
$this->notify();
}
public function getState() {
return $this->state;
}
}
// 使用示例
$subject = new Subject();
$observer1 = new ConcreteObserver('Observer 1');
$observer2 = new ConcreteObserver('Observer 2');
$subject->attach($observer1);
$subject->attach($observer2);
$subject->setState('New state');
$subject->detach($observer1);
$subject->setState('Another state');
在上面的示例中,我们定义了一个 Observer 接口,它包含了一个 update 方法,用于接收主题的状态更新。ConcreteObserver 类实现了 Observer 接口,并在 update 方法中打印接收到的更新信息。
Subject 类维护了一个观察者列表($observers),并提供了 attach 方法用于添加观察者,detach 方法用于移除观察者,以及 notify 方法用于通知所有观察者。setState 方法用于设置主题的状态,并在状态改变时调用 notify 方法通知观察者。getState 方法用于获取当前的主题状态。
在使用示例中,我们创建了一个主题对象 $subject,并将两个观察者对象 $observer1 和 $observer2 添加到主题中。然后,我们通过调用 setState 方法改变主题的状态,并观察者的 update 方法将被调用,打印接收到的更新信息。最后,我们通过调用 detach 方法移除了一个观察者,并再次改变主题的状态,观察者的更新信息将不再打印。
含义描述
装饰器设计模式是一种结构型设计模式,它允许动态地给一个对象添加一些额外的职责或功能
应用场景
代码示例
// 定义一个接口,表示被装饰的对象
interface Coffee {
public function getCost();
public function getIngredients();
}
// 创建一个实现了Coffee接口的具体对象,即被装饰的对象
class SimpleCoffee implements Coffee {
public function getCost() {
return 1.99;
}
public function getIngredients() {
return "Coffee";
}
}
// 创建一个加奶咖啡装饰器类,它包装了Coffee对象
class CoffeeWithMilk extends SimpleCoffee implements Coffee {
private $coffee;
public function __construct(Coffee $coffee) {
$this->coffee = $coffee;
}
public function getCost() {
return $this->coffee->getCost() + 0.30;
}
public function getIngredients() {
return $this->coffee->getIngredients() . ", Milk";
}
}
// 创建一个加糖咖啡的装饰器类,它也为Coffee对象添加额外的行为
class CoffeeWithSugar extends CoffeeWithMilk {
public function getCost() {
return parent::getCost() + 0.20;
}
public function getIngredients() {
return parent::getIngredients() . ", Sugar";
}
}
// 使用装饰器
$coffee = new SimpleCoffee();
echo "Cost: " . $coffee->getCost() . "\n";
echo "Ingredients: " . $coffee->getIngredients() . "\n";
$coffeeWithMilk = new CoffeeWithMilk($coffee);
echo "Cost: " . $coffeeWithMilk->getCost() . "\n";
echo "Ingredients: " . $coffeeWithMilk->getIngredients() . "\n";
$coffeeWithSugar = new CoffeeWithSugar($coffeeWithMilk);
echo "Cost: " . $coffeeWithSugar->getCost() . "\n";
echo "Ingredients: " . $coffeeWithSugar->getIngredients() . "\n";
输出结果:
Cost: 1.99
Ingredients: Coffee
Cost: 2.29
Ingredients: Coffee, Milk
Cost: 2.79
Ingredients: Coffee, Milk, Milk, Sugar
在这个示例中,我们有一个Coffee接口和两个实现了该接口的类:SimpleCoffee(被装饰的对象)和CoffeeWithMilk、CoffeeWithSugar(装饰器类)。
CoffeeWithMilk装饰器类包装了一个Coffee对象,并添加了牛奶和额外的成本。CoffeeWithSugar装饰器类进一步包装了CoffeeWithMilk对象,并添加了糖和额外的成本。
通过链式使用装饰器,我们可以动态地构建具有不同功能和成本的咖啡。
含义描述
迭代器设计模式允许你顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。通过使用迭代器,聚合对象与其迭代逻辑可以分离,从而使代码更加灵活和可扩展
应用场景
代码示例
//首先,定义一个迭代器接口(Iterator):
interface Iterator {
public function current();
public function key();
public function next();
public function rewind();
public function valid();
}
//然后,定义一个具体的迭代器类(ConcreteIterator),它实现了迭代器接口:
class ConcreteIterator implements Iterator {
private $data;
private $position = 0;
public function __construct(array $data) {
$this->data = $data;
}
public function current() {
return $this->data[$this->position];
}
public function key() {
return $this->position;
}
public function next() {
$this->position++;
}
public function rewind() {
$this->position = 0;
}
public function valid() {
return isset($this->data[$this->position]);
}
}
//接下来,定义一个聚合对象接口(Aggregate),该接口定义了一个方法来创建迭代器:
interface Aggregate {
public function createIterator();
}
//然后,创建一个实现了聚合对象接口的具体聚合类(ConcreteAggregate):
class ConcreteAggregate implements Aggregate {
private $data = [];
public function add($item) {
$this->data[] = $item;
}
public function createIterator() {
return new ConcreteIterator($this->data);
}
}
//最后,你可以使用这些类来实现迭代器的功能:
// 创建一个聚合对象
$aggregate = new ConcreteAggregate();
$aggregate->add('Element 1');
$aggregate->add('Element 2');
$aggregate->add('Element 3');
// 获取聚合对象的迭代器
$iterator = $aggregate->createIterator();
// 使用迭代器遍历聚合对象中的元素
$iterator->rewind();
while ($iterator->valid()) {
echo $iterator->current() . "\n";
$iterator->next();
}
在上面的示例中,ConcreteAggregate 类存储了一个元素数组,并提供了 createIterator() 方法来创建一个新的 ConcreteIterator 实例。ConcreteIterator 类实现了 Iterator 接口,用于遍历 ConcreteAggregate 中的元素。
更多【编程技术-php常用设计模式应用场景及示例】相关视频教程:www.yxfzedu.com