2012-07-02 2 views
1

Чтение книги Элехии Уайта «Создание встроенных систем» (из О'Рейли) меня смутило из-за этих двух терминов: шаблоны фасадов и адаптеров. Объяснение, которое она дает для обоих, не совсем понятно.Фасад против шаблонов адаптеров для встроенных систем

Adapter Pattern (Паг, 19):.. «(... Иногда называется обертка) Он преобразует интерфейс объекта в один, который проще для клиента ... Часто, адаптеры переписал программные API, чтобы скрыть уродливые интерфейсы ... ».

Фасадный шаблон (стр. 86): «... Он обеспечивает упрощенный интерфейс для фрагмента кода ...». Затем он говорит «... Шаблон адаптера - более общая версия шаблона фасада«.

К сожалению, оба термина кажутся похожими на меня.

Из других определений на этом сайте (и других) большинство людей говорят «Шаблон адаптера совместим с двумя несовместимыми интерфейсами». Что означает слово «несовместимо» означает в этом контексте?

Большинство сайтов и книг дают свои определения о шаблонах с более высокого уровня, отличного от встроенной системной точки зрения (обычная 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; 
} 

Надеется, что я объяснил достаточно хорошо себя. Заранее благодарю!!

+0

Бросьте шаблон прокси, чтобы немного смутить :) – haylem

ответ

2

The Facade pattern используется для абстрагирования сложных функций, чтобы упростить использование API.

Например, предположим, что у вас есть немного кода, который обновляет сразу несколько объектов:

ObjectA.update(); 
ObjectB.update(); 
ObjectC.update(); 

... и т.д. ...

Вы можете создать класс, который оборачивает эти три обновления() в одном звонке:

SuperObject.update(); 

Это один из примеров фасада.

Вы должны использовать шаблон адаптера, если у вас есть определенный интерфейс, который вы должны использовать, и объект, который реализует желаемое поведение, но не имеет требуемого интерфейса.

Допустим, ваш необходимый интерфейс имеет метод со следующей подписью:

void Save(); 

У вас есть класс уже который реализует необходимое поведение, но не имеет интерфейс, что нужно, возможно, что-то вроде этого:

bool Update(); 

вы не хотите, чтобы изменить существующий класс и риск поломать код, который использует его, и вы не хотите, чтобы воссоздать колесо, так что вы вместо того, чтобы создать класс-оболочку, которая реализует метод Save, но использует экземпляр вашего существующего класса:

void Save() 
{ 
    bool notUsingThisReturnValue = existingClassInstance.Update(); 
} 

Я написал статьи с изложением использования как Facade Pattern и Adapter Pattern

+1

После ваших комментариев и примеров имеет смысл сказать, что «фасадная схема» является синонимом «обертки», в отличие от определения книги, потому что на самом деле, как и в моем примере # 1, пользователю не нужно заполнять все поля, чтобы нарисовать кнопку через * fancy_gui_DrawWidget() *, поэтому он использует вместо этого более простой * mygui_DrawButton() *. * mygui_DrawButton() * "wrapping" fancy_gui_DrawWidget(). Я проверю ваши статьи, но я думаю, что я в правильном направлении =) –

0

Франциско, ваш пример для адаптера является правильным. Я могу дать еще один, но он в основном объектно-ориентированный: представьте, что у вас есть интерфейс для источников данных, у всех есть метод int readValue(), и у вас есть интерфейс с этим методом для полиморфных вызовов. И у вас есть еще один старый старый, который нельзя переписать (например, он управляется другой командой или он недоступен в исходном коде) с помощью метода int readInteger(). Вы не можете использовать свой оригинальный интерфейс с помощью метода readValue() для этого класса, поэтому вы делаете промежуточный класс, который имеет метод int readValue(), который делегирует void readInteger().

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

Теперь вы можете использовать своего старого читателя вместе со своими новыми классами и интерфейсом Reader.

В обычном мире C вы можете использовать его, если ваша функция ожидает указателя на функцию с определенной сигнатурой в качестве аргумента, а функция реализации имеет другую подпись. Просто заверните свою функцию другой с правильной подписью.

Фасад обычно используется, когда у вас есть подробный API (например, drawCircle(), drawRect(), drawLine()), но часто вам нужно использовать комбинацию этих вызовов, и вы хотите избежать копирования-вставки или не хотят предоставлять низкоуровневые абстракции для кода клиента. В этом случае вы просто использовать этот код:

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

Вы можете использовать ту же концепцию с функциями (не-ООП) API в простом C, если речь идет о встроенной.

+0

Так что я мог бы понять «шаблон адаптера» как своего рода преобразование, от одной уже существующей подписи, до более новой или другой более полезно при определенных обстоятельствах. Я довольно shure, я не могу использовать «преобразование» в этом контексте, но это заставляет меня думать более четко. –

Смежные вопросы