2012-07-02 36 views
1

通过Elecias White的书“制作嵌入式系统”(来自O'Reilly)让我感到困惑,因为这两个术语:Facade和Adapter模式。她给出的解释都不明确。面向嵌入式系统的适配器模式

适配器模式(PAG,19):“(...有时也被称为包装)这一个对象的接口转换成一个为客户更容易...通常情况下,适配器被改写软件API来隐藏难看的界面......“

外观模式(PAG 86):“......它提供了一个简化的接口的一段代码...”。然后它说:“......适配器模式是门面模式的更一般的”

可悲的是这两个词似乎与我相似。

从这个网站(和其他人)的其他定义大多数人都说“适配器模式使兼容的两个接口不兼容”。这个词是什么“不相容”的意思是在这种情况下?

大多数网站和书籍从嵌入式系统的角度(普通的C,而不是OOP)以外的更高级别给出了他们对模式的定义,所以给出的例子的确并不清楚。

值得一提的是,虽然书是知识的极好来源,对于初学者和专业人士,其中不包括这么多的代码,所以应该搞清楚这种定义。

我试图通过我为自己写的一些例子来理解它们,你会告诉我我的理解是否正确吗?

实施例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

Facade模式用来抽象掉复杂的功能,以使一个API更容易使用。

举例来说,假设你有一些代码,在一次更新多个对象:

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

...等...

你可以创建一个包装这三个更新类()呼叫为单个呼叫:

SuperObject.update(); 

这是门面的一个示例。

当您需要使用特定接口以及实现所需行为但没有所需接口的对象时,您将使用Adapter模式。

比方说,你需要的接口有以下签名的方法:

void Save(); 

你有一个类已经实现必要的行为,但没有你需要的界面,或许是这样的:

bool Update(); 

你不想改变使用它现有的类和风险断码,你也不希望重新发明轮子,所以你不是创建一个实现保存方法,但使用实例的包装类你现有的班级:

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

我写文章,介绍使用Facade Pattern都和Adapter Pattern

+1

在您的评论和示例之后,更有意义的说,“facade模式”是“包装器”的同义词,与书中的定义不同,因为事实上,正如在我的示例#1中,用户不需要填写所有字段以便通过* fancy_gui_DrawWidget()*绘制按钮,因此他使用的是更简单的* mygui_DrawButton()*。 * mygui_DrawButton()*是“包装”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(); 
    } 
} 

现在,您可以将您的旧版阅读器与新的类和界面阅读器一起使用。

在普通的C语言世界中,如果函数期望有一个指向特定签名作为参数的函数的指针,并且实现函数具有另一个签名,则可以使用它。只需用正确的签名包装你的功能。

当您有详细的API(例如drawCircle(),drawRect(),drawLine())时,通常会使用外观,但通常您需要使用此调用的组合,并且您希望避免复制粘贴或不想为客户端代码提供低级抽象。 在这种情况下,你只需使用此代码:

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

,如果你是在谈论嵌入您可以使用的功能(未OOP)API相同的概念在纯C。

+0

所以我可能会理解“适配器模式”作为某种转换,从一个已经存在的签名到另一个,或到另一个在某些情况下更有用。我很舒服,我不能在这种情况下使用“转换”,但这让我觉得更清楚。 –