PHP中的设计模式和常用设计模式有哪些?

什么是设计模式?

在软件开发中,设计模式是一种可重复使用的解决方案,用于解决常见问题。它是一种经过验证的最佳实践,可用于解决特定情况下的常见问题。

常见的设计模式

1.单例模式

单例模式是一种创建型模式,它确保类只有一个实例,并提供了全局访问点。

class Singleton {
  private static $instance = null;

  private function __construct() {}

  public static function getInstance() {
    if (self::$instance == null) {
      self::$instance = new Singleton();
    }
    return self::$instance;
  }
}

$instance1 = Singleton::getInstance();
$instance2 = Singleton::getInstance();

在上述代码中,我们通过getInstance()方法获取Singleton类的唯一实例。如果$instance1和$instance2都指向同一个对象,则表明该类只有一个实例。

2.工厂模式

工厂模式是一种创建型模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪个类。它将对象的创建和使用分离开来。

interface Car {
  public function drive();
}

class BMW implements Car {
  public function drive() {
    echo "Driving BMW";
  }
}

class Audi implements Car {
  public function drive() {
    echo "Driving Audi";
  }
}

class CarFactory {
  public static function createCar($type) {
    switch ($type) {
      case 'BMW':
        return new BMW();
        break;
      case 'Audi':
        return new Audi();
        break;
      default:
        throw new Exception('Unknown car type');
    }
  }
}

$car = CarFactory::createCar('BMW');
$car->drive();

在上述代码中,我们通过CarFactory类的createCar()方法创建了一个Car对象。根据参数$type的值,我们可以创建不同的对象。

3.观察者模式

观察者模式是一种行为型模式,它定义了对象间的一种一对多的依赖关系,以便当一个对象的状态发生变化时,其所有依赖项都会收到通知并自动更新。

interface Observer {
  public function update($data);
}

class Subject {
  private $observers = [];

  public function attach(Observer $observer) {
    $this->observers[] = $observer;
  }

  public function detach(Observer $observer) {
    $key = array_search($observer, $this->observers, true);
    if ($key !== false) {
      unset($this->observers[$key]);
    }
  }

  public function notify($data) {
    foreach ($this->observers as $observer) {
      $observer->update($data);
    }
  }
}

class EmailObserver implements Observer {
  public function update($data) {
    echo "Sending email notification: " . $data;
  }
}

class LogObserver implements Observer {
  public function update($data) {
    echo "Logging notification: " . $data;
  }
}

$subject = new Subject();
$subject->attach(new EmailObserver());
$subject->attach(new LogObserver());
$subject->notify('Something happened');

在上述代码中,我们定义了一个Subject类和两个Observer类:EmailObserver和LogObserver。当Subject类的状态发生变化时,它会通知所有观察者,并调用它们的update()方法。

常用的设计模式

除了上述常见的设计模式外,还有许多其他常用的设计模式,如适配器模式、装饰器模式、代理模式、策略模式等。

1.适配器模式

适配器模式是一种结构型模式,它允许将不兼容的对象包装在适配器中,以便它们可以共同工作。

interface MediaPlayer {
  public function play($type, $filename);
}

interface AdvancedMediaPlayer {
  public function playVlc($filename);
  public function playMp4($filename);
}

class VlcPlayer implements AdvancedMediaPlayer {
  public function playVlc($filename) {
    echo "Playing vlc file: " . $filename;
  }

  public function playMp4($filename) {
    // do nothing
  }
}

class Mp4Player implements AdvancedMediaPlayer {
  public function playVlc($filename) {
    // do nothing
  }

  public function playMp4($filename) {
    echo "Playing mp4 file: " . $filename;
  }
}

class MediaAdapter implements MediaPlayer {
  private $advancedMediaPlayer;

  public function __construct($type) {
    switch ($type) {
      case 'vlc':
        $this->advancedMediaPlayer = new VlcPlayer();
        break;
      case 'mp4':
        $this->advancedMediaPlayer = new Mp4Player();
        break;
      default:
        throw new Exception('Unknown media type');
    }
  }

  public function play($type, $filename) {
    switch ($type) {
      case 'vlc':
        $this->advancedMediaPlayer->playVlc($filename);
        break;
      case 'mp4':
        $this->advancedMediaPlayer->playMp4($filename);
        break;
      default:
        throw new Exception('Unknown media type');
    }
  }
}

class AudioPlayer implements MediaPlayer {
  private $mediaAdapter;

  public function play($type, $filename) {
    switch ($type) {
      case 'mp3':
        echo "Playing mp3 file: " . $filename;
        break;
      case 'vlc':
      case 'mp4':
        $this->mediaAdapter = new MediaAdapter($type);
        $this->mediaAdapter->play($type, $filename);
        break;
      default:
        throw new Exception('Unknown media type');
    }
  }
}

$audioPlayer = new AudioPlayer();
$audioPlayer->play('mp3', 'song.mp3');
$audioPlayer->play('vlc', 'movie.vlc');
$audioPlayer->play('mp4', 'movie.mp4');

在上述代码中,我们定义了一个MediaPlayer接口和两个AdvancedMediaPlayer接口:VlcPlayer和Mp4Player。当需要播放不支持的媒体类型时,我们使用MediaAdapter类将其转换为支持的类型。我们还定义了一个AudioPlayer类,它可以播放mp3、vlc和mp4文件。

2.装饰器模式

装饰器模式是一种结构型模式,它允许在不改变对象接口的情况下,动态地向对象添加功能。

interface Shape {
  public function draw();
}

class Circle implements Shape {
  public function draw() {
    echo "Shape: Circle";
  }
}

class Rectangle implements Shape {
  public function draw() {
    echo "Shape: Rectangle";
  }
}

abstract class ShapeDecorator implements Shape {
  protected $shape;

  public function __construct(Shape $shape) {
    $this->shape = $shape;
  }

  public function draw() {
    $this->shape->draw();
  }
}

class RedShapeDecorator extends ShapeDecorator {
  public function draw() {
    $this->shape->draw();
    echo "Border Color: Red";
  }
}

$circle = new Circle();
$rectangle = new Rectangle();

$redCircle = new RedShapeDecorator(new Circle());
$redRectangle = new RedShapeDecorator(new Rectangle());

$circle->draw();
$rectangle->draw();
$redCircle->draw();
$redRectangle->draw();

在上述代码中,我们定义了一个Shape接口和两个实现类:Circle和Rectangle。我们还定义了一个抽象类ShapeDecorator,它实现了Shape接口,并包含一个Shape对象。我们通过创建RedShapeDecorator类来扩展ShapeDecorator类以添加红色边框功能。最后,我们使用这些类来画出不同形状的图形。

3.代理模式

代理模式是一种结构型模式,它提供了一个代理对象来控制对另一个对象的访问。

interface Image {
  public function display();
}

class RealImage implements Image {
  private $filename;

  public function __construct($filename) {
    $this->filename = $filename;
    $this->loadFromDisk($filename);
  }

  public function display() {
    echo "Displaying " . $this->filename;
  }

  private function loadFromDisk($filename) {
    echo "Loading " . $filename . " from disk";
  }
}

class ProxyImage implements Image {
  private $filename;
  private $realImage;

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

  public function display() {
    if ($this->realImage == null) {
      $this->realImage = new RealImage($this->filename);
    }
    $this->realImage->display();
  }
}

$image = new ProxyImage('test.jpg');
$image->display();

在上述代码中,我们定义了一个Image接口和一个实现类:RealImage。我们通过创建ProxyImage类来控制RealImage对象的访问。当需要显示图片时,我们使用ProxyImage类来获取RealImage对象并调用其display()方法。

4.策略模式

策略模式是一种行为型模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。

interface Strategy {
  public function doOperation($num1, $num2);
}

class OperationAdd implements Strategy {
  public function doOperation($num1, $num2) {
    return $num1 + $num2;
  }
}

class OperationSubtract implements Strategy {
  public function doOperation($num1, $num2) {
    return $num1 - $num2;
  }
}

class OperationMultiply implements Strategy {
  public function doOperation($num1, $num2) {
    return $num1 * $num2;
  }
}

class Context {
  private $strategy;

  public function __construct(Strategy $strategy) {
    $this->strategy = $strategy;
  }

  public function executeStrategy($num1, $num2) {
    return $this->strategy->doOperation($num1, $num2);
  }
}

$context = new Context(new OperationAdd());
echo "10 + 5 = " . $context->executeStrategy(10, 5);

$context = new Context(new OperationSubtract());
echo "10 - 5 = " . $context->executeStrategy(10, 5);

$context = new Context(new OperationMultiply());
echo "10 * 5 = " . $context->executeStrategy(10, 5);

在上述代码中,我们定义了一个Strategy接口和三个实现类:OperationAdd、OperationSubtract和OperationMultiply。我们通过创建Context类来使用这些策略。当需要执行特定的策略时,我们使用Context类,并传递相应的策略对象。

结论

PHP中有许多常见的设计模式,这些模式可以用于解决不同的问题。了解这些模式可以帮助我们更好地设计和开发应用程序。

本文来源:词雅网

本文地址:https://www.ciyawang.com/x6quka.html

本文使用「 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 」许可协议授权,转载或使用请署名并注明出处。

相关推荐