web-dev-qa-db-ja.com

ファサードパターンは抽象化レイヤーとどのように異なりますか?

ファサードパターンについて読んだところ、クライアント(コンピューターのユーザー)がstartComputer()メソッドを呼び出してすべての複雑なものを呼び出すこの例を見つけました:

出典:wikipedia

_/* Complex parts */

class CPU {
    public void freeze() { ... }
    public void jump(long position) { ... }
    public void execute() { ... }
}

class Memory {
    public void load(long position, byte[] data) { ... }
}

class HardDrive {
    public byte[] read(long lba, int size) { ... }
}

/* Facade */

class Computer {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public Computer() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void startComputer() {
        cpu.freeze();
        memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
        cpu.jump(BOOT_ADDRESS);
        cpu.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        Computer facade = new Computer();
        facade.startComputer();
    }
}
_

ここで、クライアントクラス(あなた)がstartComputer()メソッドを呼び出して新しいファサードを作成しているのを確認できます。このメソッドは、いくつかのオブジェクトをインスタンス化してそれらのメソッドを呼び出し、それを_'glues it together'_であるファサードクラス内にカプセル化します。

質問1:

しかし、これは抽象化のレイヤーとどう違うのですか?

昨日、doLogin($username, $password)がユーザーのログイン情報を更新する_'complex'_下層メソッド呼び出しをカプセル化し、複数のオブジェクトでログインしてインスタンス化するようにセッションを設定するWebアプリケーションのログイン機能を作成しました。この仕事をする。

この層は、アクティベーションステータスのチェック、アカウントの存在、ハッシュアルゴリズムによる文字列の処理など、CRUDに似た操作を処理するさらに低いレベルも呼び出します。このメソッド(モデルレベルでは、以下の「レイヤーの概要」を参照)は、_'success'_キーまたは_'error_message'_キーは、それを呼び出すレイヤーへのソートのブール値として機能します。

これは、_'abstraction layers'_として知られているもので、上位レベルのアーキテクチャから複雑なプロシージャを隠していますが、ファサードパターンについて読んだとき、それをずっと使用していたようです。

質問2:

ログインメカニズムを抽象化するための私のアプローチは、MVCアーキテクチャでは悪い選択でしょうか?(そうでなければ、例を挙げてください)

最終結果がどこに行くか(HTML、AJAXなど)を決定するのは非常に簡単であることを考慮に入れると、これはコントローラー層で処理できるため、IFの多くを避けるための賢明な選択ではないでしょうか?

レイヤーの概要:

コントローラーレイヤー:$model->doLogin(POST VARIABLES HERE)

モデルレイヤー:(これはファサードですか?)セッションの設定、データベースのログイン情報の更新など、情報の独立したコンポーネントの呼び出し:$user_id = $user->getId();および$session->sessionExists();

独立クラスレイヤー:このレイヤーの各クラスは独立しており、結合はほとんどありません。結局のところ、それはなぜでしょうか?アプリケーションを構築し、それを制御するためのAPIを貸すのは、上のレイヤーの仕事です。

質問3:

ファサードパターンは、APIのような形式でサブクラスへの呼び出しをルーティングするためにのみ使用されますか、それともおそらく最も一般的ですか?

つまり、オブジェクトAはオブジェクトBをインスタンス化し、独自のメソッドを介してオブジェクトBのメソッドを制御するメソッドを貸し出します。

_<?php

class A {
    private $_objectB;

    public function __construct()
    {
        $this->_objectB = new B();
    }

    public function callMethodB()
    {
        $this->_objectB->methodB();
    }
}

class B {
    public function methodB()
    {
        die('Wuhu!');
    }
}

// --------------------------
$objectA->callMethodB(); // Wuhu!
_

の代わりに:

_$objectA->objectB->methodB(); // Wuhu!
_
7
Seralize

2つの関係: ファサードパターン は、「抽象化の層」のサブセットです。ファサードは、抽象化の追加レベルです。すべての抽象化がファサードであるとは限りません。

具体的には、Facadeは、複雑なAPIへの簡略化されたインターフェースを提供する場所です。多くの場合、1つの単純なクラスに多数の複雑なクラスをラップしています。たまに、複雑なAPIを持つ1つのクラスを取得し、呼び出し元のコードのためにそれを単純化している場合もあります。

同じインターフェイスを持つ別のクラスに1つの呼び出しを転送するだけの場合、より正確には プロキシパターン になります。これは、別のタイプの抽象化レイヤーです。

MVCパターンでログアウトを抽象化することは良い考えですか?はい(ほとんどのMVCフレームワークがこれを行います)。ただし、プロキシを使用して抽象化するか、ファサードを使用して抽象化するかは、ログインAPIに大きく依存します。

9
pdr

あなたはそれを完全に間違っていると解釈しています。 1行に要約すると、「ファサードパターンは、複雑なサブシステムの機能を使用できる簡略化されたインターフェイスを提供します」。ファサードパターンの使用例は、複雑なサービス/パッケージ/コンポーネントなどの基本的な低レベルメソッドへのアクセサーを提供することです。

ファサードのユースケースには、次のものは含まれません。

  1. プロセスの抽象化(これは一部の場合がありますが、これが唯一の目的であってはなりません)
  2. プロセスを1つのプロセスにカプセル化する

ファサードは、すべての低レベルのメソッドに対して1つの具体的な実装を提供するためにのみ使用されます

サブシステムと複雑さにまで及ぶ複雑なパッケージを設計する場合、一般にファサードパターンを使用する必要があります。 Facadeは、複雑なサービス/パッケージ/コンポーネントなどの基本的なlopwレベルのメトジョドへの単なるアクセサーです。

例:

ステップ1

インターフェースを作成します。

Shape.Java

public interface Shape {
   void draw();
}

ステップ2

同じインターフェースを実装する具象クラスを作成します。

Rectangle.Java

public class Rectangle implements Shape {

   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}

Square.Java

public class Square implements Shape {

   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}

Circle.Java

public class Circle implements Shape {

   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}

ステップ

ファサードクラスを作成します。

ShapeMaker.Java

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

ステップ4

ファサードを使用して、さまざまなタイプの形状を描きます。

FacadePatternDemo.Java

public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();

      shapeMaker.drawCircle();
      shapeMaker.drawRectangle();
      shapeMaker.drawSquare();      
   }
}

ステップ5

出力を確認します。

Circle::draw()
Rectangle::draw()
Square::draw()

このパターンには、クライアントに必要な簡略化されたメソッドを提供し、既存のシステムクラスのメソッドへの呼び出しを委任する単一のクラスが含まれます。

1
Viraj Khatavkar