ある日、技術部門の責任者が、技術部門の従業員全員の勤務状況を知りたいと言い、次の日、人事部門の責任者が、従業員全員の給与を知りたいと言いました。従業員。毎回、結合モードを使用して従業員を横断し、従業員の関連情報を取得します。たぶん、あなたはすべての情報を出力すればよいと言うでしょう。それでは、上司はパフォーマンスを知りたがっているでしょう。いいですか、家に帰ってください。この問題を解決するには、訪問者パターンを使用してください。クラス図は次のとおりです。
ご覧のとおり、訪問者があり、エージェントに少し似ています。プロキシ モードについて説明する際、訪問者モードについてはすでに説明しましたが、この購入ではさらに特別な場合にプロキシ モードが使用されます。実装コード:
<?php interface IVisitor{ public function visitCommonEmployee( CommonEmployee $commonEmployee ); public function visitManager( Manager $manager ); } class Visitor implements IVisitor{ public function visitCommonEmployee( CommonEmployee $commonEmployee ) { echo $this->getCommonEmployee( $commonEmployee ); } public function visitManager( Manager $manager ) { echo $this->getManagerInfo( $manager ); } private function getBasicInfo( Employee $employee ) { $info = "姓名:".$employee->getName()."\t"; return $info; } private function getCommonEmployee( CommonEmployee $commonEmployee ) { $basicInfo = $this->getBasicInfo( $commonEmployee ); $otherInfo = "工作:".$commonEmployee->getJob()."\n"; return $basicInfo.$otherInfo; } private function getManagerInfo( Manager $manager ) { $basicInfo = $this->getBasicInfo( $manager ); $otherInfo = "业绩:".$manager->getPerformance()."\n"; return $basicInfo.$otherInfo; } } abstract class Employee { private $name; public function getName() { return $this->name; } public function setName( $name ) { $this->name = $name; } public function accept( IVisitor $visitor ) { $method = 'visit'.get_class( $this ); $visitor->$method( $this ); } } class CommonEmployee extends Employee{ private $job; public function getJob() { return $this->job; } public function setJob( $job ) { $this->job = $job; } } class Manager extends Employee{ private $performance; public function getPerformance() { return $this->performance; } public function setPerformance( $performance ) { $this->performance = $performance; } } $empList = array(); $zhangsan = new CommonEmployee(); $zhangsan->setName( '张三' ); $zhangsan->setJob( 'coding' ); $empList[] = $zhangsan; $lisi = new CommonEmployee(); $lisi->setName( '李四' ); $lisi->setJob( 'coding' ); $empList[] = $lisi; $wangwu = new Manager(); $wangwu->setName( '马云' ); $wangwu->setPerformance( '负值,但拍马屁厉害' ); $empList[] = $wangwu; foreach ($empList as $value) { $value->accept(new Visitor()); } ?>
動作結果:
名前: Zhang San 仕事: コーディング
名前: Li Si 仕事: コーディング
名前: Jack Ma パフォーマンス: ネガティブだけど、お世辞は素晴らしい
[0.4秒で終了]
今後、特別なリストがあれば、特別な訪問者を追加するだけで済みます。これで、上司は私を虐待できなくなります。
訪問者パターンの定義
は、特定のデータ構造の各要素に作用するいくつかの操作をカプセル化し、データ構造を変更せずにこれらの要素に作用する新しい操作を定義できます。主な役割は次のとおりです:
1. VIsitor - 抽象訪問者
訪問者がアクセスできる要素を宣言する抽象クラス インターフェイス。訪問メソッドのパラメーターは、アクセスできるオブジェクトを定義します。
2. 具体的な訪問者——具体的な訪問者
それは、訪問者が授業を訪問した後に何をすべきかに影響します。
3. 要素 — 抽象要素
どのタイプの訪問者を受け入れるかを宣言するインターフェイスまたは抽象クラス。accept メソッドのパラメーターを通じて定義されます。
4. ConcreteElement - 具象要素
は、基本的にパターンを形成する accept メソッド (通常は Visitor->visitor($this)) を実装します。
5. ObjectStruture - 構造オブジェクト
要素ジェネレーター。通常、異なるクラスとインターフェイスの複数のコンテナーに対応します。
訪問者パターンの利点1. 単一責任の原則に従う特定の要素の役割はデータのロードを担当する Employee 抽象クラスの 2 つのサブクラスであり、Visitor クラスはレポートの表示を担当します。 2 つの異なる責任は非常に明確に分離されており、それぞれが変更を実行します。 2. 優れたスケーラビリティ 責任が分離されているため、データに対する操作を継続的に追加するのが非常に高速です。たとえば、大きなボスにレポートを追加したい場合、メソッドを直接追加できます。訪問者がデータを転送し、それを整理して印刷します。 3. 非常に高い柔軟性 たとえば、レポートと同時に合計給与を計算する必要があるとします 訪問者モデルの欠点1. 訪問者は、訪問者に詳細を公開する必要があります。 class このクラスはいくつかのメソッドとデータを公開します。これは、訪問者が他のクラスの内部詳細に注意を払うことを意味しますが、これはデメテルの法則では推奨されていません。 2. 特定の要素を変更するのは難しい 特定の要素の役割を追加、削除、変更するのは難しい 上の例では、年齢などのメンバー変数を追加する場合、訪問者は次のことを行う必要があります。訪問者が複数の場合、全員を変更する必要があるということでしょうか? 3. 依存関係の逆転の原則に違反します訪問者は抽象的な要素ではなく具体的な要素に依存するため、特にオブジェクト指向プログラミングでは、インターフェイスへの依存を放棄して直接依存することが困難になります。クラスと拡張機能を実装します。 訪問者パターンの使用シナリオ1. オブジェクト構造には多くのクラス オブジェクトが含まれており、それらのオブジェクトにはさまざまなインターフェイスがあり、これらのオブジェクトに対して特定のクラスに依存する操作を実行したい場合、つまり反復子パターンでは実行できなくなります。有能な状況。 2. オブジェクト構造内のオブジェクトに対して、多くの異なる関連性のない操作を実行する必要があり、これらの操作によってオブジェクトのクラスが「汚染」されることは避けたいです
訪問者パターンの拡張
1.統計関数たとえば、全従業員の賃金をカウントしたい場合は、インターフェイスにメソッドを追加し、特定のクラスに実装するだけで済みます。 2. 複数の訪問者 前に述べたように、異なる訪問者が異なるレポート要件を持っている場合は、Visitor クラスの実装を直接追加するだけです。 3. デュアル ディスパッチ (JAVA)
しつこい: ビジター モードは集中化された通常のモードで、特に大規模な再構築に適しています。この段階では要件が非常に明確になっており、元の機能のポイントも明確になっています。システムもビジター モードを通じて、統合レポート計算や UI 表示などの機能集中という最終目標を達成するためにいくつかの機能を簡単に整理できることは明らかです。また、他のモードとブレンドして、独自のフィルターまたはインターセプターのセットを作成します。