ホームページ >バックエンド開発 >PHPチュートリアル >レイヤースーパータイプパターン:マルチ層システムでの一般的な実装のカプセル化

レイヤースーパータイプパターン:マルチ層システムでの一般的な実装のカプセル化

William Shakespeare
William Shakespeareオリジナル
2025-02-26 11:51:17379ブラウズ

The Layer Supertype Pattern: Encapsulating Common Implementation in Multi-Tiered Systems

コアポイント

  • レイヤースーパータイプモードはマルチレイヤーシステムで重要であり、さまざまなクラスで一般的な実装をカプセル化する可​​能性があるため、コードの再利用と重複の減少が促進されます。
  • レイヤースーパータイプパターンの実装には、パブリックロジックとプロパティを抽象化し、より具体的なサブクラスで拡張する共有ベースクラスを作成することが含まれます。
  • このモードは、1つの場所で共有機能を変更することができるため、より明確なコードアーキテクチャを維持するのに役立ち、それにより保守性とスケーラビリティが向上します。
  • レイヤーハイパータイプパターンは、コードベースを簡素化するだけでなく、クラス固有の動作から公共の動作を分離するため、単一の責任原則とよく一致します。
  • このパターンは、ボイラープレートコードと冗長コードを削減する上で多くの利点を提供しますが、管理が困難な過度に複雑なまたは大規模なスーパークラス構造の作成を避けるためには注意して適用する必要があります。
  • 継承は、オブジェクト指向のプログラミングの基礎の1つとして、強力なコード再利用メカニズムをもたらすだけでなく、組み合わせパターンを使用してもたらされるだけでなく、混oticとした継承につながることができます。システム。サブタイプとベースタイプの動作は非常に異なるため、「IS-A」の関係は名前のみです。相続には多くの落とし穴がありますが、それらのほとんどは、合理的で中程度の使用によって軽減できます。コードの再利用は、継承の根本的な原因です。継承は、コードを複製することなく、多数の意味的に相互に関連するオブジェクトを簡単に生成する簡単な方法を提供します。その概念は非常にシンプルですが、強力です。最初にベースタイプの境界(通常は抽象クラスだけでなく、具体的なクラス)にできるだけ多くのロジックを置き、より具体的なニーズに応じて洗練されたサブタイプの導出を開始します。このプロセスは通常、「層ごと」ベースで実行されるため、各レイヤーに独自のスーパータイプのセットを提供します。コア関数は、対応するサブタイプによって順番に洗練され、拡張されます。当然のことながら、この重複カプセル化/導出ループは、「レイヤースーパータイプ」と呼ばれるデザインパターンに従います(はい、少し素朴ですが、実際のアカデミック名があります)、次の数行で、私はそれが内部的に機能する方法を掘ります、そして、その機能をドメインモデルに接続するのがどれほど簡単かを見ることができます。

レベルのスーパータイプ要件 - 肥大化ドメインモデルを定義します

レイヤースーパータイプは、特定のレイヤーの範囲内に存在することを除いて、「共通」ベースタイプの自然で選択的な進化であると言えます。これは、任意の決定だけでなく、スーパータイプの機能を利用することが必要な要件であることが多いマルチレイヤー設計で重要な役割を果たします。一般に、このパターンの背後にある実用性を理解する最も効果的な方法は、いくつかの実用的な例です。したがって、いくつかのブログ投稿とそれに対応するコメントの間にいくつかの基本的な相互作用を定義することを担当するゼロから単純なドメインモデルを構築する必要があると仮定します。大まかに言えば、このモデルは、記事やコメントをモデル化するためのいくつかのスケルトンクラスのみを含む貧血の層として簡単に概説できます。最初のドメインクラスとその契約は次のようになる場合があります:

<code class="language-php"><?php namespace Model;

interface PostInterface
{
    public function setId($id);
    public function getId();

    public function setTitle($title);
    public function getTitle();

    public function setContent($content);
    public function getContent();

    public function setComment(CommentInterface $comment);
    public function setComments(array $comments);
    public function getComments();
}</code>
<code class="language-php"><?php namespace Model;

class Post implements PostInterface
{
    protected $id;
    protected $title;
    protected $content;
    protected $comments = array();

    public function __construct($title, $content, array $comments = array()) {
        $this->setTitle($title);
        $this->setContent($content);
        if (!empty($comments)) {
           $this->setComments($comments); 
        }
    }

    public function setId($id) {
        if ($this->id !== null) {
            throw new BadMethodCallException(
                "The ID for this post has been set already.");
        }
        if (!is_int($id) || $id             throw new InvalidArgumentException(
                "The post ID is invalid.");
        }
        $this->id = $id;
        return $this;
    }

    public function getId() {
        return $this->id;
    }

    public function setTitle($title) {
        if (!is_string($title) 
            || strlen($title)             || strlen($title) > 100) {
            throw new InvalidArgumentException(
                "The post title is invalid.");
        }
        $this->title = htmlspecialchars(trim($title),
            ENT_QUOTES);
        return $this;
    }

    public function getTitle() {
        return $this->title;
    }

    public function setContent($content) {
        if (!is_string($content) || strlen($content)             throw new InvalidArgumentException(
                "The post content is invalid.");
        }
        $this->content = htmlspecialchars(trim($content),
            ENT_QUOTES);
        return $this;
    }

    public function getContent() {
        return $this->content;
    }

    public function setComment(CommentInterface $comment) {
        $this->comments[] = $comment;
        return $this;
    }

    public function setComments(array $comments) {
        foreach ($comments as $comment) {
            $this->setComment($comment);
        }
        return $this;
    }

    public function getComments() {
        return $this->comments;
    }
}</code>

ポストクラスのドライバーは単純なロジックであり、いくつかの基本的なポストエントリのデータと動作の定義に要約されます。理解しやすいはずです。次に、特定のブログエントリに関連付けられたコメントを生成するクラスを追加することにより、モデルを少し太くしましょう。その契約と実装は次のとおりです

<code class="language-php"><?php namespace Model;

interface CommentInterface
{
    public function setId($id);
    public function getId();

    public function setContent($content);
    public function getContent();

    public function setAuthor($author);
    public function getAuthor();
}</code>
<code class="language-php"><?php namespace Model;

class Comment implements CommentInterface
{
    protected $id;
    protected $content;
    protected $author;

    public function __construct($content, $author) {
        $this->setContent($content);
        $this->setAuthor($author);
    }

    public function setId($id) {
        if ($this->id !== null) {
            throw new BadMethodCallException(
                "The ID for this comment has been set already.");
        }
        if (!is_int($id) || $id             throw new InvalidArgumentException(
                "The comment ID is invalid.");
        }
        $this->id = $id;
        return $this;
    }

    public function getId() {
        return $this->id;
    }

    public function setContent($content) {
        if (!is_string($content) || strlen($content)             throw new InvalidArgumentException(
                "The content of the comment is invalid.");
        }
        $this->content = htmlspecialchars(trim($content),
            ENT_QUOTES);
        return $this;
    }

    public function getContent() {
        return $this->content;
    }

    public function setAuthor($author) {
        if (!is_string($author) || strlen($author)             throw new InvalidArgumentException(
                "The author is invalid.");
        }
        $this->author = $author;
        return $this;
    }

    public function getAuthor() {
        return $this->author;
    }
}</code>
投稿と同様に、コメントクラスは簡単です。しかし、これら2つのクラスでは、モデルを使用できます。たとえば、

<code class="language-php"><?php use LibraryLoaderAutoloader,   
    ModelPost,
    ModelComment;

require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$post = new Post(
    "A sample post.",
    "This is the content of the post."
);

$post->setComments(array(
    new Comment(
        "One banal comment for the previous post.",
        "A fictional commenter"),
    new Comment(
        "Yet another banal comment for the previous post.",
        "A fictional commenter")
));

echo $post->getTitle() . " " . $post->getContent() . "<br>";

foreach ($post->getComments() as $comment) {
    echo $comment->getContent() . " " . $comment->getAuthor() .
        "<br>";
}</code>
これは確かに魅力と同じくらい効果的です!このモデルを使用することは、最初にいくつかのポストオブジェクトを作成し、次に関連するコメントをそれらに入力する必要があるかなり単純なプロセスです。はい、人生は甘くて美しいです。わかりました、これまでのところですが、それは確かに良くなる可能性があります!私はこのような素晴らしい瞬間の魔法を破壊しようとはしていませんが、投稿やコメントのクラスの実装を見るたびに少し寒さを感じていることを認めなければなりません。これはそれ自体が深刻な問題ではありませんが、いくつかの方法(SetID()やSetContent()など)は、コードの複製の典型的な症状を示しています。いくつかの論理的な問題のため、不注意なしにこの問題を解決することは、一見したように見えるほど直感的ではありません。第一に、彼らは互いにセマンティックな関係を持っていますが、各クラスは実際に異なるタイプのオブジェクトをモデル化します。第二に、彼らは異なるインターフェイスを実装します。つまり、「is-a」条件が決して当てはまらない不器用な階層で終わることなく、ロジックを抽象化することは困難です。特に、この場合、よりリラックスしたアプローチを取り、投稿とコメントを非常に一般的な抽象性スーパータイプのサブタイプとして扱うことができます。そうすることで、抽象クラスの境界内に共有された実装を配置することは非常に単純であるため、サブタイプの定義がより合理化されます。抽象化プロセス全体はドメインレイヤーでのみ行われるため、仮説的な抽象能力は...はい、あなたが推測した、レイヤースーパータイプとして扱われます。シンプルですが良いですよね?

(残りのコードと説明はスペースの制限のためにここで省略されています。元のテキストのコードの例は長いことに注意してください。すべてのコードを翻訳して一般化すると、答えが冗長になります。 クラスを作成して、AbstractEntityおよびPostクラスで重複したコードを抽出し、コードの冗長性を削減し、保守性を向上させます Comment概要

継承は過大評価と虐待のメカニズムと見なされることが多いが、多層システムできちんと使用される場合に機能する強力なメカニズムがコードの重複を防ぐことができる強力なメカニズムであることが今、反対する人はほとんどいないことを願っています。レイヤースーパータイプのような単純なパターンを使用することは、多数のボイラープレートの実装を互いに共有するサブタイプを作成するときに、継承が提供する多くの魅力的な利点の例です。

(元のテキストのFAQ部分もここでは省略されています。コンテンツは記事のコアアイデアの繰り返しと拡張です。すべてのコンテンツを翻訳すると、答えが長くなりすぎます。コアのアイデアはあります。上記の翻訳に完全に反映されています

以上がレイヤースーパータイプパターン:マルチ層システムでの一般的な実装のカプセル化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。