1

Elecias White の著書「Making Embedded Systems」 (O'Reilly から) を読んで、Facade パターンと Adapter パターンという 2 つの用語のために混乱しました。彼女が両方について与える説明は、まったく明確ではありません。

Adapter Pattern (Pag, 19): 「(...ラッパーと呼ばれることもあります)オブジェクトのインターフェースをクライアントにとってより簡単なものに変換します.....多くの場合、アダプターは醜いインターフェースを隠すためにソフトウェア API の上に書かれています. ..」 .

Facade パターン(Pag. 86): 「...コードへの簡素化されたインターフェイスを提供します...」. 次に、「...アダプターパターンはファサードパターンのより一般的なバージョンです」と表示されます。

悲しいことに、どちらの用語も私には似ているように思えます。

このサイト (および他のサイト) の他の定義から、ほとんどの人は「アダプター パターンにより、互換性のない 2 つのインターフェイスが互換性を持つようになる」と言います。この文脈で「相容れない」という言葉はどういう意味ですか?

ほとんどのサイトや書籍では、組み込みシステムの観点 (OOP ではなくプレーン C) 以外のより高いレベルからのパターンに関する定義が示されているため、示されている例は実際には明確ではありません。

この本は、初心者と専門家の両方にとって優れた知識源ですが、それほど多くのコードが含まれていないため、この種の定義を理解する必要があることに注意してください。

私が自分用に書いたいくつかの例を通してそれらを理解しようとしましたが、私の理解が正しいかどうか教えていただけますか?

例 1、ファサード パターン:

/* This is a fancy API that I want to 'facade' */

fancy_gui_DrawWidget(parent, id, x0, y0, x1, y1, text, txt_color, back_color, brdr_color, draw_callback(), ... and more parameters)
{
/* draw the widget */
}


/* Here I'm using the 'facade pattern' */

mygui_DrawButton(parent, id, x, y, width, height, text)
{
 ...
x1=x+width;
y1=y+height;
...

fancy_gui_DrawWidget(parent, id, x, y, x1, y1, text, BLACK, WHITE, ORANGE, button_draw_fn, ... and some more parameters needed);
}

例 2、アダプターのパターン:

/* Ugly interface that I want to 'adapt' (from LPC17xx NXP's CMSIS library) */

uint32_t UART_Send(
LPC_UART_TypeDef *UARTx, 
uint8_t *txbuf,
uint32_t buflen, 
TRANSFER_BLOCK_Type flag)
{
/* transmits the txbuf */
}

/* Here I'm using the 'adapter pattern' (I think so) for a good looking interface */

int uart0_Send(buffer, len_buffer)
{
/* Do some stuff */
len=UART_Send(uart0_handler,buffer,len_buffer, BLOCKING);
if(len!=len_buffer)
return 0;
return 1;
}

私が自分で十分に説明したことを願っています。よろしくお願いします!

4

2 に答える 2

0

フランシスコ、アダプターの例は正しいです。もう1つ挙げることができますが、ほとんどの場合、オブジェクト指向です。データソースのインターフェイスにはすべてメソッド int readValue()があり、ポリモーフィック呼び出しにはこのメソッドのインターフェイスがあると想像してください。また、メソッドを使用して書き換えることができない古いレガシーがもう1つあります(たとえば、他のチームによって管理されているか、ソースコードで利用できません) int readInteger()。このクラスのメソッドで元のインターフェイスを使用することはできないため、に委任するメソッドreadValue()を持つ中間クラスを作成します。int readValue()void readInteger()

class Adapter implements Reader {
  private LegacyReader legacyReader;
  public int readValue() {
       return legacyReader.readInteger();
  }
}

これで、レガシーリーダーを新しいクラスおよびインターフェイスリーダーと一緒に使用できます。

プレーンCの世界では、関数が引数として特定のシグネチャを持つ関数へのポインタを持っていることを期待し、実装関数が別のシグネチャを持っている場合に使用できます。関数を正しい署名付きの別の関数でラップするだけです。

ファサードは通常、詳細なAPI(たとえば、drawCircle()、drawRect()、drawLine())がある場合に使用されますが、多くの場合、この呼び出しの組み合わせを使用する必要があり、コピー&ペーストを避けたい、または望まない場合クライアントコードに低レベルの抽象化を提供します。この場合、次のコードを使用するだけです。

class DrawerFacade {
   private LowLevelDrawer drawer;
   public void drawHouse(int i, int j) {
       drawer.drawCircle(...);
       drawer.drawRect(...);
   }
}

組み込みについて話している場合は、プレーンCの関数(非OOP)APIで同じ概念を使用できます。

于 2012-07-02T20:53:11.523 に答える