>백엔드 개발 >PHP 튜토리얼 >PHP 디자인 패턴 배우기 PHP는 방문자 패턴(Visitor)_php 기술을 구현합니다.

PHP 디자인 패턴 배우기 PHP는 방문자 패턴(Visitor)_php 기술을 구현합니다.

WBOY
WBOY원래의
2016-05-16 20:03:501003검색

방문자 패턴은 객체 구조의 각 요소에 작용하는 작업을 나타냅니다. 각 요소 클래스를 수정하지 않고도 이러한 요소에 대해 작동하는 새로운 작업을 정의할 수 있습니다. 즉, 특정 방문자 역할을 동적으로 추가할 수 있습니다.
방문자 패턴은 이중 파견을 활용합니다. 먼저 방문자를 요소 개체의 Accept 메서드에 전달한 다음 요소 개체가 방문자에게 자신을 전달한 다음 방문자는 요소의 해당 메서드를 실행합니다.
방문자 패턴은 다양한 유형의 집계가 있을 때 주로 사용됩니다. 일반적인 형태에서는 각 요소가 어떤 유형에 속하는지 파악한 후 해당 연산을 수행해야 하므로 조건 전달문이 길어지게 됩니다. 방문자 모드는 이 문제를 더 잘 해결할 수 있습니다. 각 요소에 대해 $element->accept($vistor)를 균일하게 호출하면 됩니다.
방문자 패턴은 방문하는 클래스의 구조가 상대적으로 안정적일 때, 즉 하위 클래스가 임의로 추가되지 않을 때 주로 사용됩니다. 방문자 패턴을 사용하면 액세스된 구조에 새 메서드를 추가할 수 있습니다.
Visitor 패턴은 실제로 객체 구조의 요소와 이러한 요소를 작동하는 동작을 분리하므로 객체 구조의 요소를 기반으로 메서드를 호출할 때 IF 문을 사용하여 판단할 필요가 없습니다. 캡슐화되어 있습니다.
그러나 새로운 요소 노드가 추가되면 방문자 인터페이스와 해당 하위 클래스가 변경되어 객체 지향의 열림 및 닫힘 원리를 위반하게 됩니다.
이러한 상황이 발생하면 일반적으로 방문자 모드를 더 이상 적용할 수 없거나 디자인에 문제가 있음을 의미합니다!
1. 방문자 모드 구조도

2. 방문자 모드의 주요 캐릭터

1) 추상 방문자 역할(Visitor): 객체 구조(ObjectStructure)의 특정 요소 각각에 대한 접근 작업 인터페이스를 제공합니다. 작업 인터페이스의 이름과 매개변수는 액세스할 특정 요소 역할을 식별합니다. 이를 통해 방문자는 해당 요소 역할의 특정 인터페이스를 통해 직접 액세스할 수 있습니다.
2) 구체적인 방문자 역할(ConcreteVisitor): 추상 방문자 역할 인터페이스에서 각 특정 요소 역할에 대해 선언된 작업을 구현합니다.
3) 추상 노드(Node) 역할: 이 인터페이스는 특정 방문자를 수락하는 수락 작업을 정의합니다.
4) 구상 노드(Node) 역할: 추상 노드 역할에서 accept 연산을 구현합니다.
5) 객체 구조 역할(ObjectStructure) : 방문자 모드를 사용하기 위해 꼭 필요한 역할입니다. 이는 다음과 같은 특성을 가져야 합니다. 요소를 열거할 수 있고 방문자가 해당 요소에 액세스할 수 있도록 상위 수준 인터페이스를 제공할 수 있으며 목록 또는 순서가 지정되지 않은 컬렉션과 같은 조합일 수도 있습니다. set(PHP에서는 배열을 대신 사용합니다. 왜냐하면 PHP의 배열은 본질적으로 모든 유형의 데이터를 담을 수 있는 컬렉션이기 때문입니다.)
3. 방문자 모드의 장점과 단점
방문자 모드에는 다음과 같은 장점이 있습니다.
1) 방문자 모드를 사용하면 새로운 작업을 쉽게 추가할 수 있습니다. 특정 요소 클래스를 수정하지 않고 새 작업을 추가하려면 방문자 패턴을 사용하세요. 주로 요소 클래스의 accept 메소드를 통해 새로운 방문자 객체를 받아들이는 방식으로 구현됩니다. 일부 작업이 복잡한 구조 개체에 의존하는 경우 일반적으로 새 작업을 추가하는 것이 복잡해집니다. 방문자 패턴을 사용하면 새로운 연산을 추가한다는 것은 새로운 방문자 클래스를 추가한다는 의미이므로 쉬워진다.
2) 방문자 패턴은 관련 행위를 노드 클래스로 분산시키는 대신 방문자 개체에 집중합니다.
3) 방문자 모드는 여러 클래스의 계층 구조에 걸쳐 서로 다른 계층 구조에 속하는 멤버 클래스에 액세스할 수 있습니다. 반복자는 동일한 유형 계층에 속하는 멤버 개체에만 액세스할 수 있지만 다른 계층에 속한 개체에는 액세스할 수 없습니다. 방문자 패턴이 이를 수행할 수 있습니다.
4) 축적현황. 각각의 개별 방문자 개체는 관련 행위를 집중시켜 실행 작업의 상태가 여러 노드 개체에 흩어지는 것이 아니라 접속 과정에서 자체적으로 누적될 수 있도록 합니다. 이는 시스템 유지 관리에 유리합니다.

방문자 모드에는 다음과 같은 단점이 있습니다.
1) 새로운 노드 클래스를 추가하는 것이 어려워집니다. 새 노드를 추가할 때마다 추상 방문자 역할에 새 추상 작업을 추가하고 각 구체적인 방문자 클래스에 해당하는 구체적인 작업을 추가하는 것을 의미합니다.
2) 패키지를 파기합니다. 방문자 패턴에서는 방문자 개체가 각 노드 개체의 작업에 액세스하고 호출해야 하며 이는 모든 노드 개체에 대한 요구 사항을 의미합니다. 즉, 자체 작업 및 내부 상태 중 일부를 노출해야 합니다. 그렇지 않으면 방문자의 방문이 의미가 없게 됩니다. 방문자 개체 자체는 액세스 작업에 필요한 상태를 축적하므로 이러한 상태는 더 이상 노드 개체에 저장되지 않으며 이로 인해 캡슐화가 중단됩니다.

방문자 모드 사용을 위한 전제 조건: 개체 그룹 구조(컬렉션)의 개체 유형은 거의 변경되지 않습니다.
방문자 및 요소 인터페이스에서는 요소가 거의 변경되지 않도록 해야 합니다. 즉, 새 요소 요소 유형이 자주 추가되지 않도록 해야 합니다. 변경할 수 있는 것은 방문자의 동작이나 작업, 즉 방문자의 하위 클래스 수입니다. be 방문자 모드를 사용하는 가장 편리한 방법입니다.
객체 컬렉션의 객체 컬렉션이 자주 변경되면 Visitor 구현도 변경해야 할 뿐만 아니라 ConcreteVisitor도 해당 동작을 추가해야 합니다. GOF에서는 이러한 객체에서 작업을 하나씩 직접 정의하는 것이 더 낫다는 것을 제안합니다. 방문자 디자인 패턴을 사용하지 않고 수업을 진행합니다.

4. 방문자 모드 및 기타 모드

1. 탐색 중인 구조 객체가 선형인 경우 방문자 모드 대신 반복 모드를 사용할 수도 있습니다
2. 방문자 모드는 합성 모드의 일부 구조 개체를 탐색합니다
위의 두 가지 요점은 "Java and Patterns"라는 책에서 나온 것입니다

5. 방문자 모드 PHP 예제

<&#63;php
 
interface Visitor {
 public function visitConcreteElementA(ConcreteElementA $elementA);
 public function visitConcreteElementB(concreteElementB $elementB);
}
 
interface Element {
 public function accept(Visitor $visitor);
}
 
/**
 * 具体的访问者1
 */
class ConcreteVisitor1 implements Visitor {
 public function visitConcreteElementA(ConcreteElementA $elementA) {
 echo $elementA->getName() . " visitd by ConcerteVisitor1 <br />";
 }
 
 public function visitConcreteElementB(ConcreteElementB $elementB) {
 echo $elementB->getName() . " visited by ConcerteVisitor1 <br />";
 }
 
}
 
/**
 * 具体的访问者2
 */
class ConcreteVisitor2 implements Visitor {
 public function visitConcreteElementA(ConcreteElementA $elementA) {
 echo $elementA->getName() . " visitd by ConcerteVisitor2 <br />";
 }
 
 public function visitConcreteElementB(ConcreteElementB $elementB) {
 echo $elementB->getName() . " visited by ConcerteVisitor2 <br />";
 }
 
}
 
/**
 * 具体元素A
 */
class ConcreteElementA implements Element {
 private $_name;
 
 public function __construct($name) {
 $this->_name = $name;
 }
 
 public function getName() {
 return $this->_name;
 }
 
 /**
 * 接受访问者调用它针对该元素的新方法
 * @param Visitor $visitor
 */
 public function accept(Visitor $visitor) {
 $visitor->visitConcreteElementA($this);
 }
 
}
 
/**
 * 具体元素B
 */
class ConcreteElementB implements Element {
 private $_name;
 
 public function __construct($name) {
 $this->_name = $name;
 }
 
 public function getName() {
 return $this->_name;
 }
 
 /**
 * 接受访问者调用它针对该元素的新方法
 * @param Visitor $visitor
 */
 public function accept(Visitor $visitor) {
 $visitor->visitConcreteElementB($this);
 }
 
}
 
/**
 * 对象结构 即元素的集合
 */
class ObjectStructure {
 private $_collection;
 
 public function __construct() {
 $this->_collection = array();
 }
 
 
 public function attach(Element $element) {
 return array_push($this->_collection, $element);
 }
 
 public function detach(Element $element) {
 $index = array_search($element, $this->_collection);
 if ($index !== FALSE) {
 unset($this->_collection[$index]);
 }
 
 return $index;
 }
 
 public function accept(Visitor $visitor) {
 foreach ($this->_collection as $element) {
 $element->accept($visitor);
 }
 }
}
 
class Client {
 
 /**
 * Main program.
 */
 public static function main() {
 $elementA = new ConcreteElementA("ElementA");
 $elementB = new ConcreteElementB("ElementB");
 $elementA2 = new ConcreteElementB("ElementA2");
 $visitor1 = new ConcreteVisitor1();
 $visitor2 = new ConcreteVisitor2();
 
 $os = new ObjectStructure();
 $os->attach($elementA);
 $os->attach($elementB);
 $os->attach($elementA2);
 $os->detach($elementA);
 $os->accept($visitor1);
 $os->accept($visitor2);
 }
 
}
 
Client::main();
&#63;>

위는 PHP를 사용하여 방문자 모드를 구현하는 코드입니다. 또한 방문자 모드에 대한 몇 가지 개념적 차이가 모든 사람의 학습에 도움이 되기를 바랍니다.

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