이 글은 PHP에 대한 관련 지식을 제공하며, 주로 몇 가지 일반적인 개발 모델을 소개합니다. 모두에게 도움이 되기를 바랍니다.
디자인 패턴의 6가지 원칙
개방 및 폐쇄 원칙: 클래스, 모듈, 기능과 같은 소프트웨어 엔터티는 확장에는 개방적이고 수정에는 폐쇄적이어야 합니다.
리히터 대체 원칙: 기본 클래스를 참조하는 모든 장소는 해당 하위 클래스의 객체를 투명하게 사용할 수 있어야 합니다.
종속성 반전 원칙: 상위 수준 모듈은 하위 수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 합니다. 추상화는 세부사항에 의존해서는 안 됩니다. 세부사항은 추상화에 의존해야 합니다.
단일 책임 원칙: 수업 변경에 대한 이유가 두 가지 이상이어서는 안 됩니다. 평신도의 관점에서 보면 클래스는 단 하나의 책임만 담당합니다.
인터페이스 격리 원칙: 클라이언트는 필요하지 않은 인터페이스에 의존해서는 안 됩니다. 한 클래스가 다른 클래스에 종속되는 것은 가장 작은 인터페이스를 기반으로 해야 합니다.
데미터의 법칙: 객체는 다른 객체에 대해 최소한의 지식을 유지해야 합니다.
특징: 싱글턴 모드를 사용하면 새로운 작업에 많은 리소스가 소비되는 것을 피할 수 있습니다.
싱글턴 클래스는 직접 인스턴스화 및 생성할 수 없지만 클래스에 의해서만 인스턴스화될 수 있습니다. 그 자체. 따라서 이러한 제한적인 효과를 얻으려면 생성자를 비공개로 표시하여 클래스가 인스턴스화되지 않도록 해야 합니다.
클래스 인스턴스를 저장하고 인스턴스에 액세스할 수 있는 공용 정적 메서드를 노출하려면 전용 정적 멤버 변수가 필요합니다.
PHP에서는 다른 사람이 싱글톤 클래스 인스턴스를 복제하는 것을 방지하기 위해 일반적으로 빈 개인 __clone() 메서드가 제공됩니다.
$_instance는 정적 개인 변수로 선언되어야 합니다
생성자와 소멸자는 외부 프로그램이 새 클래스를 생성하여 싱글톤 모드의 의미를 잃지 않도록 하기 위해 개인으로 선언해야 합니다
getInstance( ) 메소드를 설정해야 합니다. 공개의 경우 이 메소드를 호출하여 인스턴스에 대한 참조를 반환해야 합니다
:: 연산자는 정적 변수 및 정적 함수에만 액세스할 수 있습니다
새 객체는 메모리를 소비합니다
사용법 시나리오: 가장 일반적으로 사용되는 장소는 데이터베이스 연결입니다.
싱글턴 패턴을 사용하여 객체를 생성한 후 해당 객체는 다른 많은 객체에서 사용될 수 있습니다.
개인 __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(){}}
Factory 모드, 팩토리 메소드 또는 클래스는 코드에서 직접 객체를 생성합니다.
클래스를 인스턴스화하려면 new 메서드를 사용하세요. 클래스를 인스턴스화할 때마다 팩토리 클래스의 메서드만 호출하면 됩니다.
장점: 클래스가 여러 곳에서 인스턴스화될 수 있기 때문입니다. 클래스 이름이나 매개변수가 변경되면 팩토리 클래스 아래의 메소드에서 한 번만 팩토리 패턴을 쉽고 빠르게 수정할 수 있어 인스턴스화된 객체를 하나씩 수정할 필요가 없습니다.
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('autoload1'); $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('autoload1'); $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);.
등록 모드는 글로벌 공유 및 교환 개체를 해결합니다. 생성된 객체는 전역적으로 사용 가능한 배열에 걸려 있으며, 필요할 경우 배열에서 직접 가져올 수 있습니다. 전역 트리에 개체를 등록합니다. 어디든 직접 가서 방문해보세요.
<?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]);//移除某个注册到树上的对象。 }}
전략 패턴은 특정 동작 및 알고리즘 세트를 특정 특정 상황에 맞게 클래스로 캡슐화합니다.
예: 전자상거래 웹사이트 시스템이 있는 경우 남성과 여성 사용자는 서로 다른 제품 카테고리로 이동해야 하고 모든 광고 공간에는 서로 다른 광고가 표시됩니다. 전통적인 코드에서는 다양한 판단이 하드 코딩된 방식으로 시스템에 추가됩니다. 어느 날 사용자가 추가되면 코드를 다시 작성해야 합니다. 정책 모드를 사용하면 새 사용자 유형을 추가하는 경우 정책만 추가하면 됩니다. 다른 모든 것에는 다른 전략이 필요합니다.
먼저 전략의 인터페이스 파일을 선언하고 전략에 포함된 동작을 규정합니다. 그런 다음 각 특정 전략 구현 클래스를 정의합니다.
UserStrategy.php
<?php /*• 声明策略文件的接口,约定策略包含的行为 */interface UserStrategy { function showAd(); function showCategory(); }FemaleUser.php <?phprequire_once 'Loader.php'; class FemaleUser implements UserStrategy { function showAd() { echo "2016冬季女装"; }function showCategory(){ echo "女装"; }} MaleUser.php <?phprequire_once 'Loader.php'; class MaleUser implements UserStrategy { function showAd(){ echo "IPhone6s"; }function showCategory(){ echo "电子产品"; }} Page.php//执行文件 <?php require_once 'Loader.php'; 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();
요약:
위의 방법을 통해 서로 다른 사용자가 로그인하면 서로 다른 컨텐츠가 표시되는 것을 확인할 수 있지만 표시 중 하드 코딩 문제는 해결됩니다. 전략을 추가하려면 전략 구현 클래스를 추가한 다음 항목 파일에서 판단을 수행하고 이 클래스를 전달하기만 하면 됩니다. 디커플링을 달성합니다. 인터페이스를 통해 종속성 반전 및 제어 반전을 구현합니다. 클래스 간에 직접적인 종속성은 없습니다. 이 클래스를 사용하면 인터페이스의 구현 클래스가 동적으로 전달됩니다. 클래스를 교체하려면 해당 인터페이스를 구현하는 구현 클래스만 제공하면 되며, 코드 한 줄만 수정하면 교체가 완료됩니다.
观察者模式(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"
装饰器模式, 根据运行时不同的情景动态地为某个对象调用前后添加不同的行
一个类提供了一项功能,如果要在修改并添加额外的功能,传统的编程模式,需要写一个子类继承它,并重写实现类的方法,使用装饰器模式,仅需要在运行时添加一个装饰器对象即可实现,可以实现最大额灵活性
场景:
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='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='font-size: {$this->size}px'>"; } public function after() { echo "</div>"; } }//实例化输出类 echo->addDecorator(new ColorDecorator('red')); //增加装饰器 echo->Index(); //输出<dis style='color: red'><dis style='font-size: 22px'>你好,我是装饰器。</div></div>
将一个类的接口转换成客户希望的另一个接口,适配器模式使得原本的由于接口不兼容而不能一起工作的那些类可以一起工作。
场景:老代码接口不适应新的接口需求,或者代码很多很乱不便于继续修改,或者使用第三方类库。例如: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 중국어 웹사이트의 기타 관련 기사를 참조하세요!