ホームページ  >  記事  >  バックエンド開発  >  PHP におけるいくつかの一般的な開発パターン

PHP におけるいくつかの一般的な開発パターン

WBOY
WBOY転載
2023-01-03 14:20:544442ブラウズ

この記事では、PHP に関する関連知識を紹介し、主にいくつかの一般的な開発モデルを紹介します。一緒に見ていきましょう。皆様のお役に立てれば幸いです。

PHP におけるいくつかの一般的な開発パターン

デザイン パターンの 6 つの原則

オープンとクローズの原則: クラス、モジュール、関数などのソフトウェア エンティティはオープンである必要があります。拡張子であり、変更は禁止されています。

Richter 置換原則: 基本クラスを参照するすべての場所は、そのサブクラスのオブジェクトを透過的に使用できなければなりません。

依存関係逆転原則: 高レベルのモジュールは低レベルのモジュールに依存すべきではありません。 、両方ともその抽象化に依存する必要があり、抽象化は詳細に依存すべきではなく、詳細は抽象化に依存する必要があります。

単一責任の原則: クラス変更の理由は複数あってはならない。平たく言えば、クラスは 1 つの責任だけを担当します。

インターフェイス分離の原則: クライアントは、必要のないインターフェイスに依存すべきではありません。あるクラスの別のクラスに対する依存関係は、最小のインターフェイスに基づく必要があります。

デメテルの法則: オブジェクトは、他のオブジェクトに関する最小限の知識を保持する必要があります。

1. シングルトン モード:

機能: シングルトン モードを使用すると、新しい操作によって消費される大量のリソースを回避できます

シングル ケース クラスインスタンス化によって直接作成することはできません。クラス自体によってのみインスタンス化できます。したがって、このような制限効果を得るには、コンストラクターをプライベートとしてマークし、クラスがインスタンス化されないようにする必要があります。

クラス インスタンスを保存し、インスタンスにアクセスできるパブリック静的メソッドを公開するには、プライベート静的メンバー変数が必要です。

PHP では、他のユーザーがシングルトン クラス インスタンスを複製できないようにするために、通常、空のプライベート __clone() メソッドが提供されます。

  • #$_instance は静的プライベート変数として宣言する必要があります

  • 外部プログラムが新しいインスタンスを作成しないように、コンストラクターとデストラクターはプライベートとして宣言する必要がありますシングルトン モードの意味が失われます

  • #getInstance() メソッドを public に設定する必要があり、インスタンスへの参照を返すにはこのメソッドを呼び出す必要があります
  • ::Operator は静的変数と静的関数にのみアクセスできます
  • 新しいオブジェクトはメモリを消費します
  • 使用シナリオ:最も一般的に使用される場所はデータベース接続です。
  • シングルトン パターンを使用してオブジェクトを生成した後、そのオブジェクトは他の多くのオブジェクトで使用できます。
  • プライベート __clone() メソッドはオブジェクトのクローン作成を防止します
  • <?php
    
    class Singleton{
    
    //私有属性,用于保存实例
    
    private static $instance;
    
    //构造方法私有化,防止外部创建实例
    
    private function __construct(){}//公有方法,用于获取实例
    public static function getInstance(){
        //判断实例有无创建,没有的话创建实例并返回,有的话直接返回
        if(!(self::$instance instanceof self)){
            self::$instance = new self();
        }
        return self::$instance;
    }
    //克隆方法私有化,防止复制实例
    private function __clone(){}}
  • 2. ファクトリ モード

ファクトリ モード、ファクトリ メソッドまたはクラスはコード内で new ではなくオブジェクトを直接生成します。

Use メソッド new を使用してクラスをインスタンス化します。各インスタンス化では、インスタンス化するためにファクトリ クラス内のメソッドを呼び出すだけで済みます。

利点: クラスはさまざまな場所でインスタンス化できるため。クラス名やパラメータが変更された場合、ファクトリ クラスの下のメソッド内でファクトリ モードを簡単かつ迅速に変更できるため、インスタンス化されたオブジェクトを 1 つずつ変更する必要がなくなります。

Test1.php

<?php

class Test1

{

static function test()

{

echo FILE;

}

}Factory.php

<?php

class Factory

{

/**

*如果某个类在很多的文件中都new ClassName(),那么万一这个类的名字

*发生变更或者参数发生变化,如果不使用工厂模式,就需要修改每一个PHP

*代码,使用了工厂模式之后,只需要修改工厂类或者方法就可以了。

*/

static function createDatabase()

{

$test = new Test1();

return $test;

}

}

Test.php

<?php

spl_autoload_register(&#39;autoload1&#39;);

$test = Factory::createDatabase();

$test->test();function autoload1($class)
{
    $dir = __DIR__; 
    $requireFile = $dir."\".$class.".php"; 
    require $requireFile; 
}}
Test1.php

<?php

class Test1

{

protected static tt)

{

echo "对象已经创建<br>";

return self::tt = new Test1();

echo "创建对象<br>";

return self::$tt;

}

}function echoHello()
{
    echo "Hello<br>"; 
}}
Test.php

<?php

spl_autoload_register(&#39;autoload1&#39;);

$test = Test1::getInstance();

$test->echoHello();

$test = Test1::getInstance();

$test->echoHello();

$test = Test1::getInstance();

$test->echoHello();

$test = Test1::getInstance();

$test->echoHello();function autoload1($class)
{ 
    $dir = __DIR__; 
    $requireFile = $dir."\".$class.".php"; 
    require $requireFile; 
}}

たとえば、長方形と円が同じメソッドを持つと仮定すると、基本クラスが提供する API を使用してインスタンスを作成すると、パラメーターを渡すことで、対応するクラスのインスタンスが自動的に作成されます。境界関数とエリア関数

<?php

interface InterfaceShape

{

function getArea();

function getCircumference();

}/**
• 矩形

*/

class Rectangle implements InterfaceShape

{

private $width;

private $height;
public function __construct($width, $height)

{

$this->width = $width;

$this->height = $height;

}
public function getArea()

{

return $this->width* $this->height;

}
public function getCircumference()

{

return 2 * $this->width + 2 * $this->height;

}

}/**
• 圆形

*/

class Circle implements InterfaceShape

{

private $radius;
function __construct($radius)

{

$this->radius = $radius;

}
public function getArea()

{

return M_PI * pow($this->radius, 2);

}
public function getCircumference()

{

return 2 * M_PI * $this->radius;

}

}/**
• 形状工厂类

*/

class FactoryShape

{

public static function create()

{

switch (func_num_args()) {

case1:

return newCircle(func_get_arg(0));

case2:

return newRectangle(func_get_arg(0), func_get_arg(1));

default:

# code...

break;

}

}

}rect);

echo "<br>";// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
circle);

3. 登録モード

登録モードは、グローバル共有およびオブジェクト交換を解決します。作成されたオブジェクトはグローバルに使用できる配列上に保持され、必要に応じて配列から直接取得できます。オブジェクトをグローバルツリーに登録します。どこからでも直接アクセスできます。

<?php

class Register

{

protected static $objects;//将对象注册到全局的树上 
function set($alias,$object)
{ 
    self::$objects[$alias] = $object;//将对象放到树上 
} 

static function get($name)
{ 
    return self::$objects[$name];//获取某个注册到树上的对象 
} 

function _unset($alias)
{ 
    unset(self::$objects[$alias]);//移除某个注册到树上的对象。
}}

4. 戦略パターン

戦略パターンは、特定の特定のコンテキストに適応するために、特定の動作とアルゴリズムのセットをクラスにカプセル化します。

例: 電子商取引 Web サイト システムがある場合、男性と女性のユーザーは異なる商品カテゴリにジャンプする必要があり、すべての広告スロットに異なる広告が表示されます。従来のコードでは、さまざまな if else 判定がハードコーディングされた方法でシステムに追加されます。ある日ユーザーが追加された場合、コードを書き直す必要があります。ポリシー モードを使用して、新しいユーザー タイプを追加する場合は、ポリシーを追加するだけで済みます。それ以外の場合は、別の戦略が必要になります。

最初にストラテジのインターフェイス ファイルを宣言し、ストラテジに含まれる動作を規定します。次に、それぞれの特定の戦略実装クラスを定義します。
UserStrategy.php

<?php

/*• 声明策略文件的接口,约定策略包含的行为

*/interface UserStrategy {

function showAd();

function showCategory();

}FemaleUser.php

<?phprequire_once &#39;Loader.php&#39;;
class FemaleUser implements UserStrategy {

function showAd() {

echo "2016冬季女装";

}function showCategory(){
     echo "女装"; 
}}
MaleUser.php

<?phprequire_once &#39;Loader.php&#39;;
class MaleUser implements UserStrategy {

function showAd(){

echo "IPhone6s";

}function showCategory(){ 
    echo "电子产品"; 
}}
Page.php//执行文件
<?php
require_once &#39;Loader.php&#39;;
class Page {

protected $strategy;function index(){ 
    echo "AD";
    $this->strategy->showAd(); 
    echo "<br>"; 
    echo "Category"; 

    $this->strategy->showCategory(); 
    echo "<br>"; 
} 

function setStrategy(UserStrategy $strategy){ 
    $this->strategy = $strategy; 
}}
$page = new Page();
if(isset($_GET['male'])){

$strategy = new MaleUser();

}else {

$strategy = new FemaleUser();

}strategy);

$page->index();

要約:

上記の方法により、異なるユーザーがログインすると異なるコンテンツが表示されることがわかりますが、表示時のハードコーディングの問題は解決されています。 。ストラテジを追加したい場合は、ストラテジ実装クラスを追加し、エントリーファイルで判定を行い、このクラスに渡すだけです。デカップリングを実現します。依存関係の反転と制御の反転を実装します (理解してください)。インターフェイスを通じて、クラス間に直接の依存関係はありません。このクラスを使用する場合、インターフェイスの実装クラスが動的に渡されます。クラスを置き換える場合は、インターフェースを実装する実装クラスを提供するだけでよく、コードを 1 行変更するだけで置き換えが完了します。

5.观察者模式

观察者模式(Observer),当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新(一个对象通过提供方法允许另一个对象即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者)
场景1:一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。

场景2: 用户登录,需要写日志,送积分,参与活动等;使用消息队列,把用户和日志,积分,活动之间解耦合

观察者模式实现了低耦合,非侵入式的通知与更新机制。

<?php
/*

观察者接口

*/

interface InterfaceObserver

{

function onListen($sender, $args);

function getObserverName();

}// 可被观察者接口

interface InterfaceObservable

{

function addObserver(observer_name);

}// 观察者抽象类

abstract class Observer implements InterfaceObserver

{

protected $observer_name;function getObserverName()

{

return $this->observer_name;

}function onListen($sender, $args)

{}

}// 可被观察类

abstract class Observable implements InterfaceObservable

{

protected $observers = array();public function addObserver(observerinstanceofInterfaceObserver)

{

$this->observers[] = $observer;

}

}public function removeObserver(this->observersas $index => observer->getObserverName() === this->observers, $index, 1);

return;

}

}

}

}// 模拟一个可以被观察的类

class A extends Observable

{

public function addListener(this->observersas $observer)

{
this, $listener);

}

}

}// 模拟一个观察者类

class B extends Observer

{

protected $observer_name = 'B';public function onListen($sender, sender);

echo "<br>";

var_dump($args);

echo "<br>";

}

}// 模拟另外一个观察者类

class C extends Observer

{

protected $observer_name = 'C';public function onListen($sender, sender);

echo "<br>";

var_dump($args);

echo "<br>";

}

}a->addObserver(new B());

$a->addObserver(new C());// 可以看到观察到的信息

$a->addListener('D');// 移除观察者

$a->removeObserver('B');// 打印的信息:

// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }

// string(1) "D"

// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }

// string(1) "D"

6.装饰器模式

装饰器模式, 根据运行时不同的情景动态地为某个对象调用前后添加不同的行
一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重写实现类的方法,使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大额灵活性

场景:

1.symfony 控制器中beforepost afterpost 中post提交前和提交后,对数据处理

2.当某一功能或方法draw,要满足不同的功能需求时,可以使用装饰器模式

/**
• 输出一个字符串
• 装饰器动态添加功能
• Class EchoText

*/

class EchoText

{

protected $decorator = [];
public function Index()

{

//调用装饰器前置操作

$this->beforeEcho();

echo "你好,我是装饰器。";

//调用装饰器后置操作

$this->afterEcho();

}
//增加装饰器

public function addDecorator(Decorator $decorator)

{

$this->decorator[] = $decorator;

}
//执行装饰器前置操作 先进先出原则

protected function beforeEcho()

{

foreach ($this->decorator as $decorator)

$decorator->before();

}
//执行装饰器后置操作 先进后出原则

protected function afterEcho()

{
this->decorator);

foreach ($tmp as $decorator)

$decorator->after();

}

}/**
• 装饰器接口
• Class Decorator

*/

interface Decorator

{

public function before();
public function after();

}/**
• 颜色装饰器实现
• Class ColorDecorator

*/

class ColorDecorator implements Decorator

{

protected $color;
public function __construct($color)

{

$this->color = $color;

}
public function before()

{

echo "<dis style=&#39;color: {$this->color}'>";

}
public function after()

{

echo "</div>";

}

}/**
• 字体大小装饰器实现
• Class SizeDecorator

*/

class SizeDecorator implements Decorator

{

protected $size;
public function __construct($size)

{

$this->size = $size;

}
public function before()

{

echo "<dis style=&#39;font-size: {$this->size}px'>";

}
public function after()

{

echo "</div>";

}

}//实例化输出类
echo->addDecorator(new ColorDecorator('red'));

//增加装饰器
echo->Index();

//输出<dis style=&#39;color: red&#39;><dis style=&#39;font-size: 22px&#39;>你好,我是装饰器。</div></div>

7.适配器模式

将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。
场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。例如:php连接数据库的方法:mysql,,mysqli,pdo,可以用适配器统一

//老的代码

class User {private $name;      

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

public function getName() {      
    return $this->name;      
}}
//新代码,开放平台标准接口

interface UserInterface {

function getUserName();

}class UserInfo implements UserInterface {
protected $user;      

function __construct($user) {      

    $this->user = $user;      

}      

public function getUserName() {      

    return $this->user->getName();      

}}

$olduser = new User('张三');

echo $olduser->getName()."n";olduser);

echo $newuser->getUserName()."n";

推荐学习:《PHP视频教程

以上がPHP におけるいくつかの一般的な開発パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。