>백엔드 개발 >PHP 튜토리얼 >PHP 본질 PHP 디자인 패턴

PHP 본질 PHP 디자인 패턴

WBOY
WBOY원래의
2016-07-25 09:13:12952검색

1. 가장 적합한 디자인 패턴을 선택하세요

완벽한 것은 없으며 누구도 디자인 패턴이 모든 경우에 적용되는 엄격한 솔루션이라고 말한 적이 없습니다. 따라서 이러한 모드를 변경하여 현재 작업에 더 적합하게 만들 수 있습니다. 일부 디자인 패턴의 경우 해당 패턴이 속한 프로그램에 고유한 반면, 다른 디자인 패턴의 경우 패턴 자체를 변경할 수 있습니다. 모드가 협력하고 함께 일하는 것이 일반적입니다. 이는 전체 애플리케이션의 (적어도 일부) 기초를 형성합니다.

2. 싱글톤 모드

  1. // Database 클래스는 전역 DB 연결을 나타냅니다.

  2. class Database{
  3. // 정적 변수 단일 인스턴스 유지
  4. private static $_instance = null;
  5. // 싱글톤을 보장하기 위해 생성자를 비공개로 만듭니다.
  6. private function __construct()
  7. {
  8. echo 'constructor';
  9. }

  10. // 싱글톤 인스턴스를 가져오는 메서드

  11. public static function getInstance()
  12. {
  13. if (!(self::$_instance instanceof 데이터베이스)) {
  14. self::$_instance = new Database();
  15. }
  16. return self::$_instance;
  17. }
  18. }

  19. $database = Database::getInstance();

  20. var_dump($database);

코드 복사

문제: 싱글톤 모드를 사용하여 두 개의 인스턴스를 생성할 수 없습니다. 특성을 사용하여 서로 다른 유형의 두 인스턴스를 생성하는 문제를 해결할 수 있지만 두 개의 동일한 인스턴스를 생성하는 문제는 여전히 해결되지 않습니다(레지스트리 모드로 해결 가능).

다른 클래스 코드의 두 인스턴스를 만듭니다.

  1. 특성 싱글턴 {
  2. private static $_instance = null;
  3. public static function getInstance() {
  4. $class = __CLASS__;
  5. if(!(self::$_instance 인스턴스of $class)) {
  6. self::$_instance = new $class;
  7. }
  8. return self:: $_instance;
  9. }
  10. }
  11. 클래스 DB {
  12. }
  13. 클래스 DBWriteConnection 확장 DB {
  14. 싱글톤 사용;
  15. 프라이빗 함수 __construct () {
  16. echo 'DBWriteConnection
    ';
  17. }
  18. }
  19. class DBReadConnection 확장 DB {
  20. 싱글톤 사용;
  21. 개인 함수 __construct () {
  22. echo 'DBReadConnection
    ';
  23. }
  24. }
  25. $dbWriteConnection = DBWriteConnection::getInstance();
  26. var_dump($dbWriteConnection);
코드 복사

3. 레지스트리 모드 레지스트리 패턴은 코드가 필요할 때 개체의 동일한 인스턴스를 검색하고 필요할 때 다른 인스턴스를 생성할 수 있도록 하는 단순한 단일 전역 클래스입니다(해당 전역 인스턴스는 요청 시 다시 액세스됩니다).

등록 클래스:

  1. class Registry {

  2. /**
  3. * @var array 모든 객체를 저장하는 저장소
  4. */
  5. static private $_store = array() ;
  6. /**
  7. * 레지스트리에 개체 추가
  8. *
  9. * 이름을 지정하지 않으면 클래스 이름이 사용됩니다.
  10. *
  11. * @param mix $object 저장할 개체
  12. * @param string $name 객체를 검색하는 데 사용되는 이름
  13. * @return void
  14. * @throws Exception
  15. */
  16. static public function add($object, $name = null)
  17. {
  18. // 이름이 지정되지 않은 경우 클래스 이름을 사용하고 싱글톤을 시뮬레이션합니다.
  19. $name = (!is_null($name)) ?$name:get_class($object);
  20. if (isset(self::$_store[$name])) {
  21. throw new Exception( "개체가 이미 레지스트리에 존재합니다.");
  22. }
  23. self::$_store[$name]= $object;
  24. }
  25. /**
  26. * 레지스트리에서 객체 가져오기
  27. *
  28. * @param string $name 객체 이름, {@see self::set()}
  29. * @return Mixed
  30. * @throws 예외
  31. */
  32. 정적 공용 함수 get($name)
  33. {
  34. if (!self::contains($name)) {
  35. throw new Exception("개체가 레지스트리에 존재하지 않습니다.");
  36. }

  37. return self::$_store[$name];

  38. }
  39. /**
  40. * 레지스트리에 개체가 있는지 확인
  41. *
  42. * @param string $name 개체 이름, {@see self::set()}
  43. * @return bool
  44. */
  45. 정적 공개 함수에는 다음이 포함됩니다. ($name)
  46. {
  47. if (!isset(self::$_store[$name])) {
  48. return false;
  49. }
  50. return true;
  51. }
  52. /**
  53. * 레지스트리에서 개체 제거
  54. *
  55. * @param string $name 개체 이름, {@see self::set()}
  56. * @returns void
  57. */
  58. 정적 공용 함수 제거($name)
  59. {
  60. if (self::contains($name)) {
  61. unset( self::$_store[$name]);
  62. }
  63. }
  64. }
코드 복사

클래스 외부에서는 Registry 클래스를 사용합니다.

  1. require 'Registry.php';

  2. class DBReadConnection {}

  3. class DBWriteConnection {}

  4. $read = new DBReadConnection;

  5. Registry::add($read);

  6. $write = new DBWriteConnection;

  7. Registry::add($write);

  8. // 코드 어디에서나 인스턴스를 가져오려면:

  9. $read = Registry::get( 'DBReadConnection');
  10. $write = 레지스트리::get('DBWriteConnection');

  11. var_dump($read);

  12. var_dump($write);
코드 복사

클래스 내부에 레지스트리 테이블 클래스를 사용하며, 사용자는 레지스트리와 상호 작용하지 않습니다.

샘플 코드:

  1. require 'Registry.php';

  2. 추상 클래스 DBConnection {

  3. static public function getInstance($name = null)
  4. {
  5. // __CLASS__의 후기 정적 바인딩 버전을 가져옵니다.
  6. $class = get_called_class();
  7. // 이름 전달 허용 여러 인스턴스를 얻으려면
  8. // 이름을 전달하지 않으면 싱글톤으로 작동합니다.
  9. $name = (!is_null($name)) ? $name:$class;
  10. if (!Registry ::contains($name)) {
  11. $instance = new $class();
  12. Registry::add($instance, $name);
  13. }
  14. return Registry::get($ name);
  15. }
  16. }

  17. class DBWriteConnection은 DBConnection을 확장합니다. {

  18. public function __construct()
  19. {
  20. echo 'DBWriteConnection
  21. }
  22. }

  23. class DBReadConnection은 DBConnection을 확장합니다. {

  24. 공개 함수 __construct()
  25. {
  26. echo 'DBReadConnection
  27. }
  28. }

  29. $dbWriteConnection = DBWriteConnection::getInstance('abc');

  30. var_dump($dbWriteConnection);
  31. $dbReadConnection = DBReadConnection::getInstance();
  32. var_dump($dbReadConnection);

코드 복사

4.공장 모드 공장 패턴은 이름을 딴 철강 및 콘크리트 산업과 마찬가지로 객체를 제조합니다. 일반적으로 동일한 추상 클래스나 인터페이스의 구체적인 구현을 초기화하기 위해 팩토리 패턴을 사용합니다.

일반적으로 공장 모드는 거의 사용되지 않지만 여전히 다양한 드라이버 기반 설치 변형을 초기화하는 데 가장 적합합니다. 예를 들어 다양한 구성, 세션 또는 캐싱 스토리지 엔진이 있습니다. 팩토리 패턴의 가장 큰 가치는 여러 개체 설정을 하나의 간단한 메서드 호출로 캡슐화할 수 있다는 것입니다.

  1. /**
  2. * 로그 팩토리
  3. *
  4. * 파일, mysql 또는 sqlite 로거 설정 및 반환
  5. */
  6. class Log_Factory {
  7. /**
  8. * 로그 객체 가져오기
  9. *
  10. * @param string $type 로깅 백엔드 유형, 파일, mysql 또는 sqlite
  11. * @param array $options 로그 클래스 옵션
  12. */
  13. 공용 함수 getLog( $type = 'file', array $options)
  14. {
  15. // 유형을 소문자로 정규화
  16. $type = strtolower($type);
  17. // 클래스 이름 파악
  18. $class = "Log_" .ucfirst($type);
  19. require_once str_replace('_', DIRECTORY_SEPARATOR, $class) '.php';
  20. // 인스턴스화합니다. 클래스를 선택하고 적절한 옵션을 설정
  21. $log = new $class($options);
  22. 스위치($type) {
  23. 케이스 'file':
  24. $log->setPath($options[ 'location']);
  25. break;
  26. case 'mysql':
  27. $log->setUser($options['username']);
  28. $log->setPassword($options ['password']);
  29. $log->setDBName($options['location']);
  30. break;
  31. case 'sqlite':
  32. $log->setDBPath($ options['location']);
  33. break;
  34. }
  35. return $log;
  36. }
  37. }
코드 복사

5. 반복 모드 반복 패턴을 사용하면 공용 속성뿐만 아니라 모든 개체의 내부에 저장된 데이터에 foreach의 성능을 추가할 수 있습니다. 기본 foreach 동작을 재정의하고 루프에 비즈니스 논리를 삽입할 수 있습니다.

(1) Iterator 인터페이스 사용

  1. class BasicIterator는 Iterator를 구현합니다. {

  2. private $key = 0;
  3. private $data = array(
  4. "hello",
  5. "world",
  6. );

  7. 공개 함수 __construct() {

  8. $this->key = 0;
  9. }

  10. 공개 함수 rewind() {

  11. $this->key = 0;
  12. }

  13. () {

  14. return $this->data[$this->key];
  15. }

  16. 공개 함수 키() {

  17. return $this ->key;
  18. }

  19. 공개 함수 next() {

  20. $this->key ;
  21. return true;
  22. }
  23. public function valid() {

  24. return isset($this->data[$this->key]);
  25. }
  26. }

  27. $iterator = new BasicIterator();

  28. $iterator->rewind();

  29. do {

  30. $key = $iterator- >key();
  31. $value = $iterator->current();
  32. echo $key .': ' .$value . PHP_EOL;
  33. } while ($iterator->next( ) && $iterator->valid());

  34. $iterator = new BasicIterator();
  35. foreach ($iterator as $key => $value ) {
  36. echo $key .': ' .$value . PHP_EOL;
  37. }

코드 복사

(2) RecursiveIteratorIterator를 사용하여 배열을 순회합니다.

  1. $array = array(

  2. "Hello", // 레벨 1
  3. array(
  4. " World" // 레벨 2
  5. ),
  6. array(
  7. "How", // 레벨 2
  8. array(
  9. "are", // 레벨 3
  10. "you" / / 레벨 3
  11. )
  12. ),
  13. "doing?" // 레벨 1
  14. );

  15. $recursiveIterator = new RecursiveArrayIterator($array);

  16. $recursiveIteratorIterator = new RecursiveIteratorIterator($recursiveIterator);

  17. foreach($recursiveIteratorIterator as $key => $value) {

  18. echo "깊이: " . $recursiveIteratorIterator->getDepth() . PHP_EOL;
  19. echo "키: " . $key . PHP_EOL;
  20. echo "값: " .$value .

코드 복사

(3)사용FilterIterator迭代器实现过滤

  1. class EvenFilterIterator 확장 FilterIterator {

  2. /**
  3. * 짝수 값만 허용
  4. *
  5. * @return bool
  6. */
  7. public function accept()
  8. {
  9. // 실제 반복자를 가져옵니다
  10. $iterator = $this->getInnerIterator();
  11. // 현재 키를 가져옵니다
  12. $ key = $iterator->key();
  13. // 짝수 키 확인
  14. if ($key % 2 == 0) {
  15. return true;
  16. }
  17. false 반환;
  18. }
  19. }

  20. $array = array(

  21. 0 => "안녕하세요",
  22. 1 => " Everybody Is",
  23. 2 => "나는",
  24. 3 => "Amazing",
  25. 4 => "The",
  26. 5 => "Who",
  27. 6 => "Doctor",
  28. 7 => "Lives"
  29. );

  30. // 배열에서 반복자 만들기

  31. $ iterator = new ArrayIterator($array);

  32. // FilterIterator 만들기

  33. $filterIterator = new EvenFilterIterator($iterator);

  34. foreach ($filterIterator as $key => $value) {
  35. echo $key .': '. $ 값 . PHP_EOL;
  36. }
  37. ?>

复代码

(4)RegexIterator迭代器

  1. // RecursiveDirectoryIterator 만들기
  2. $directoryIterator = new RecursiveDirectoryIterator("./" );

  3. // 재귀적으로 반복하기 위한 RecursiveIteratorIterator 생성

  4. $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);

  5. // Createa *Iterator*.php 파일에 대한 필터

  6. $regexFilter = new RegexIterator($recursiveIterator, '/(.*?)Iterator(.*?).php$/');

  7. < p>// 반복
  8. foreach ($regexFilter as $key => $file) {
  9. /* @var SplFileInfo $file */
  10. echo $file->getFilename() . PHP_EOL;
  11. }
复主代码

功能:找到所有的php文件

(4)LimitItertor迭代器,imageSQL中的LIMIT

  1. // 배열 정의

  2. $array = array(
  3. 'Hello',
  4. 'World ',
  5. '어떻게',
  6. '지금',
  7. '너',
  8. '뭐하고 있어?'
  9. );

  10. // 만들기 반복자

  11. $iterator = new ArrayIterator($array);

  12. // 처음 2개의 요소를 가져오기 위해 제한 반복자를 만듭니다

  13. $limitIterator = new LimitIterator($ iterator, 0, 2);

  14. // 반복

  15. foreach ($limitIterator as $key => $value) {
  16. echo $key .': '. $ 값 . PHP_EOL;
  17. }

复代码

6. 관찰자 모드(관찰자)

관찰자 패턴의 핵심은 애플리케이션이 특정 이벤트가 발생할 때 이를 트리거하는 콜백을 등록한다는 것입니다.

  1. /**

  2. * 이벤트 클래스
  3. *
  4. * 이 클래스를 사용하면 주어진 이벤트에 대해
  5. * 호출(FIFO)되는 콜백을 등록할 수 있습니다.
  6. */
  7. 수업 이벤트 {
  8. / **
  9. * @var array 이벤트의 다차원 배열 => 콜백
  10. */
  11. static protected $callbacks = array();
  12. /**
  13. * 콜백 등록
  14. *
  15. * @param string $eventName 트리거 이벤트 이름
  16. * @param mix $callback Event_Callback 또는 Closure의 인스턴스
  17. */
  18. 정적 공개 함수 RegisterCallback($eventName, $callback)
  19. {
  20. if (!($callback instanceof Event_Callback) && !($callback instanceof Closure)) {
  21. throw new Exception("잘못된 콜백!");
  22. }
  23. $eventName = strtolower($eventName);
  24. self::$callbacks[$eventName][] = $callback;
  25. }
  26. /**
  27. * 이벤트 트리거
  28. *
  29. * @param string $eventName 트리거할 이벤트 이름
  30. * @param mix $data 콜백으로 보낼 데이터
  31. */
  32. static public 함수 트리거($eventName, $data)
  33. {
  34. $eventName = strtolower($eventName);
  35. if (isset(self::$callbacks[$eventName])) {
  36. foreach (self::$callbacks[$eventName] as $callback) {
  37. self::callback($callback, $data);
  38. }
  39. }
  40. }
  41. / **
  42. * 콜백 수행
  43. *
  44. * @param mix $callback Event_Callback 또는 Closure의 인스턴스
  45. * @param mix $data 콜백으로 전송된 데이터
  46. */
  47. 정적 보호 함수 콜백($callback, $data)
  48. {
  49. if ($callback instanceof Closure) {
  50. $callback($data);
  51. } else {
  52. $callback->run($data);
  53. }
  54. }
  55. }

  56. /**

  57. * 이벤트 콜백 인터페이스
  58. *
  59. * 클로저를 사용하지 않으려는 경우
  60. * 대신 this를 확장하는 클래스를 정의할 수 있습니다
  61. *. run 메소드는
  62. * 이벤트가 트리거될 때 호출됩니다.
  63. */
  64. interface Event_Callback {
  65. 공용 함수 run($data);
  66. }

  67. /**

  68. * 로거 콜백
  69. */
  70. class LogCallback은 Event_Callback을 구현합니다. {
  71. 공개 함수 run($data)
  72. {
  73. echo "로그 데이터" .
  74. var_dump($data);
  75. }
  76. }

  77. Event::registerCallback('save', new LogCallback());

  78. // 캐시 지우기 콜백을 클로저로 등록

  79. 이벤트::registerCallback('save', function ($data) {
  80. echo "캐시 지우기" . PHP_EOL;
  81. var_dump($data);
  82. });

  83. < ;p>class MyDataRecord {
  84. public function save()
  85. {
  86. // 데이터 저장
  87. // 저장 이벤트 트리거
  88. Event::trigger('save', array ("Hello", "World"));
  89. }
  90. }

  91. // 새 데이터 레코드 인스턴스화

  92. $data = new MyDataRecord();
  93. $data->save(); // '저장' 이벤트가 여기서 발생합니다

코드 복사

7. 의존성 주입 모드 종속성 주입 패턴을 사용하면 클래스가 이 동작을 사용하여 이 클래스에 종속성을 주입할 수 있습니다.

  1. /**

  2. * 로그 클래스
  3. */
  4. 클래스 로그 {
  5. /**
  6. * @var Log_Engine_Interface
  7. */
  8. protected $engine = false;
  9. /**
  10. * 로그에 이벤트 추가
  11. *
  12. * @param string $message
  13. */
  14. 공개 함수 add($message)
  15. {
  16. if (!$this->engine) {
  17. throw new Exception('로그를 쓸 수 없습니다. 엔진이 설정되지 않았습니다.');
  18. }
  19. $data['datetime'] = time();
  20. $data[' message'] = $message;
  21. $session = Registry::get('session');
  22. $data['user'] = $session->getUserId();
  23. $this->engine->add($data);
  24. }
  25. /**
  26. * 로그 데이터 저장 엔진 설정
  27. *
  28. * @param Log_Engine_Interface $Engine
  29. */
  30. 공개 함수 setEngine(Log_Engine_Interface $engine)
  31. {
  32. $this->engine = $engine;
  33. }
  34. /**
  35. * 데이터 스토리지 엔진 검색
  36. *
  37. * @return Log_Engine_Interface
  38. */
  39. 공개 함수 getEngine()
  40. {
  41. return $this- >engine;
  42. }
  43. }

  44. interface Log_Engine_Interface {

  45. /**
  46. * 로그에 이벤트 추가
  47. *
  48. * @param string $message
  49. */
  50. 공용 함수 add(array $data);
  51. }

  52. class Log_Engine_File은 Log_Engine_Interface를 구현합니다. {

  53. /**
  54. * 로그에 이벤트 추가
  55. *
  56. * @param string $message
  57. */
  58. 공용 함수 add(array $data)
  59. {
  60. $line = '[' .data('r', $data['datetime']). '] ' .$data['message'] ' 사용자: ' .$data['user'] . 🎜>
  61. $config = Registry::get('site-config');
  62. if (!file_put_contents($config['location'], $line, FILE_APPEND)) {
  63. throw new Exception("파일에 쓰는 동안 오류가 발생했습니다.");
  64. }
  65. }
  66. }

  67. $engine = new Log_Engine_File();

  68. $log = new Log();

  69. $log->setEngine($engine);

  70. // 레지스트리에 추가

  71. Registry::add($log);

코드 복사
종속성 주입에는 팩토리 모드가 필요하지 않습니다. 일본 등을 이해해야 합니다. 각기 다른 스토리지 엔진에 대한 지식이 필요합니다. 이는 로깅 클래스를 사용하는 모든 개발자가 자신의 스토리지 엔진을 추가하고 인터페이스를 간단하게 구성할 수 있음을 의미합니다.

8. 모델-뷰-컨트롤러 MVC 패턴이라고도 알려진 Model-View-Controller는 애플리케이션의 서로 다른 세 가지 수준 간의 관계를 설명하는 방법입니다. 모델-데이터 계층 모든 출력 데이터는 모델에서 나옵니다. 데이터베이스, 웹 서비스 또는 파일일 수 있습니다. 뷰 표현 계층은 모델에서 데이터를 꺼내 사용자에게 출력하는 역할을 담당합니다. 컨트롤러-애플리케이션 플로우 레이어는 사용자의 요청에 따라 해당 모델을 호출하여 요청된 데이터를 검색한 후, 뷰를 호출하여 작업 결과를 사용자에게 표시합니다.

일반적인 MVC 아키텍처 다이어그램:

php mvc架构图 9. 패턴의 이해

패턴은 많은 일반적인 문제에 대한 최고의 솔루션입니다.

당신이 관심을 가질 만한 기사:

    php 디자인 패턴: 싱글턴 모드, 팩토리 모드, 관찰자 ​​모드
  • PHP 디자인 패턴 예제에 대한 심층 설명
  • php 디자인 패턴 예제 명령 패턴
  • PHP 디자인 패턴 예제 관찰자 패턴(2)
  • PHP 디자인 패턴 예제의 관찰자 패턴
  • PHP 디자인 패턴의 팩토리 패턴 예시
  • PHP 디자인 패턴 예제 싱글턴 패턴
  • PHP 디자인 패턴 예시 옵저버 패턴
  • PHP 디자인 패턴 팩토리 패턴 예제 코드
  • PHP 디자인 패턴의 싱글턴 모드 예제 코드
  • 팩토리 패턴과 싱글톤 패턴 소개, PHP 공통 디자인 패턴
  • PHP 디자인 패턴 중 싱글턴 패턴 배우기
  • PHP에서 일반적으로 사용되는 세 가지 디자인 패턴에 대한 연구 노트
  • PHP 디자인 패턴의 싱글턴 패턴 학습

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.