门面模式和网关模式的区别是什么?

68

门面模式还是网关模式?


1
我来晚了,但欢迎读者在下面评论我的答案。 - hadaytullah
12个回答

100

在《设计模式》一书中审查Facade和另一个答案中的Martin Fowler的Gateway链接时,它们的重点似乎朝着相反的方向。

Facade为一个或多个外部客户端提供了对复杂内部的简单统一视图;

Gateway为应用程序的内部提供了对外部资源的简单统一视图。

这种区别让我们关注设计中哪个更重要:

在Facade中,外部系统是我们的客户;如果使外部接口更简单,则可以将复杂性面向内部添加。

在Gateway中,内部系统是我们的客户;即使外部看起来更复杂,也要给予它所有的帮助。


1
这确实是一个重要的区别!感谢您用如此清晰明了的方式阐述它! - TheSilverBullet
如果你能通过简单的类/图表为我提供示例,我会为你的答案投上赏金,Brian... - TheSilverBullet
外观模式的问题在于它无法本地化,只能应用于架构而非应用程序。这会导致问题,因为每当必须在应用程序内部检查转发的URL上的安全性、方法或其他任何内容时,它必须通过新请求通过外观返回并重新进入。这个问题也困扰着API网关。然而,“API抽象”(http://www.slideshare.net/bobdobbes/edit_my_uploads)解决了这个问题。 - Orubel
如果需要将“internals”翻译成中文,可以翻译为“内部结构”。比如说我们已经有了一个复杂的数据结构,需要从这个结构中提取数据怎么办? - someUser

47

这两个模式在某种程度上非常相似,它们都作为某些东西的封装器。不同之处在于上下文:Facade覆盖了一组子系统,而Gateway可以覆盖任何功能。从这个角度来看,对我来说,Facade是Gateway的具体情况(而不是相反)。

当我们认为使用子系统很复杂或者想要将几个子系统调用分组到一个[方法]执行中时,就会应用Facade。然而,这并不意味着子系统不可访问,或者它们足够复杂。这只是意味着我们有子系统。

当我们希望包装某些内容并以不同的方式公开它们时,就会应用Gateway。Gateway可能不仅包装子系统,还包装相对复杂的功能。Gateway是一种通用模式,可以被视为Facade、Proxy和其他模式的基础。

如果需要进一步解释,请看以下例子:

Facade可以通过查询支票账户子系统、信贷账户子系统、储蓄子系统和后勤办公室子系统来计算客户的信用价值(我猜我在GOF图书中看过类似的例子)。

class MortgateFacade {
    bool IsCreditWorth(string customerName) {
        return !_checkingAccSystem.HasNegativeBalance(customerName) && !_creditAccSystem.HasNegativeCredit(customerName) && !_backOfficeSystem.IsInBlackList(customerName);
    }
}

网关可以查询数据库表并根据ID返回客户信息。(是的,就这么简单!)

class CustomersGateway {
    Customer GetCustomer(int id) {
        return _db.ExecuteOne("SELECT TOP 1 FROM CUSTOMERS WHERE CUSTOMER_ID="+id).AsCustomer();
    }
}

[显然这是伪代码]


1
谢谢您。Facade是网关的一个特定案例 - 我将进一步探索这个想法。如果我可以补充一下关于网关的观点,网关用于将外部系统与我们的核心系统解耦。它有助于以不同的方式表达外部API,以便明天另一个API可以取代它,对我们的系统影响最小。如果您同意或纠正我的观点,那将非常有帮助。:) 再次感谢!在它过期之前让我给您那份赏金... - TheSilverBullet
1
是的,网关可以用于将外部API转换为更方便的格式。然而,在理论上,不要将您对网关的理解局限于此。嗯,"Gateway"这个词本身就告诉你这只是一个通往某个地方的门[way],或者说是以不同的方式看待事物的另一种方式。是的,您可以在未来替换网关实现,但这与网关模式无关。我会称之为SOLID原则中的“D”(依赖反转)。把“包装器”称为网关,就到此为止。现在,您完全正确! - Tengiz

32
Facade模式的目的在http://c2.com/cgi/wiki?FacadePattern中描述为:

为一个子系统中的一组接口提供一个统一的接口。Facade定义了一个更高级别的接口,使子系统更容易使用。这可以用来简化多个复杂对象交互为单个接口。

重点在于设计一个隐藏复杂性的接口,关键是将多个细粒度的交互隐藏在一个更可用的交互中。因此,Facade的焦点是面向客户端。
网关模式不是原始GOF模式之一,我认为它更像是企业集成模式,即比Facade的层次更高。请参见Fowler的定义
我认为网关主要是为了隐藏技术复杂性而不是接口复杂性——隐藏连接到大型机和外部系统的详细信息。实际上,我经常期望网关成为请求路由器,甚至根据请求详情选择不同的后端系统。因此,我认为网关的焦点是它作为网关的内容。
显然,非正式地说,网关是一个Facade,因为它隐藏了细节,但我认为当你实现一个GOF Facade和一个Fowler Gateway时,你最终会做出非常不同的事情。

3
坦白地说,这是唯一正确的答案。 - dnickless

11

这可能有些简化,但以下是我的理解:

  • 使用外观模式可以为其他人提供与你的应用程序交互的接口。例如:你已经实现了一些拥有多个“模块”的应用程序,为了更容易地访问这些“模块”,你可以创建一个外观来使其更易于与模块交互......一个单一的联系点。
  • 使用网关模式可以封装你想要使用的某个外部部分。例如:你想要使用日志记录,但不想绑定到特定的日志框架,这种情况下你可以定义你的网关,定义你想使用的功能,并让网关处理与你想要使用的日志框架的交互。这样就很容易在将来更改日志框架了。

1
我相信这可能是最好的答案。门面模式:你将(内部)复杂系统隐藏在其后面。网关模式:你将外部系统隐藏在其后面。方向是相反的。 - wholenewstrain
不同框架的日志示例看起来像是适配器模式? - nod

11
以下是来自Fowler的书籍的直接引用:

尽管外观模式简化了更复杂的API,通常是由服务的编写者用于一般用途。网关是由客户端为其特定用途编写的。此外,外观总是意味着与其所覆盖的内容有不同的接口,而网关可以完全复制包装的外观,用于替代或测试目的。

[第18章]


1
正如Fowler在他的书《企业应用架构模式》中所说:“我必须承认,我一直在为是否将这个(网关)作为一个新模式而不是引用诸如Facade之类的现有模式而苦苦挣扎。” 即使对于他来说,这也并不简单。 - Gabriel Aramburu

8
我认为网关是门面模式的一个特例 - 它是对外部系统的一个门面。

5
简单来说,Facade 是一种设计模式,而 Gateway 是一种架构模式。
例如,应用程序网关是一种基础架构架构模式。该节点位于 DMZ 中,将内部节点与只能连接到应用程序网关的外部客户端隔离开来。
当您考虑架构模式时,请考虑节点。当您考虑设计模式时,请考虑类/对象。
节点是设备(硬件和系统软件 - 如 OS、平台/框架等)的抽象化。系统软件被“分配”给设备。节点“封装”了设备和系统软件,并与组成架构的其他节点相关联。
Gateway 是一个节点,将服务器节点与客户端节点隔离开来 - 客户端节点无法直接连接到服务器节点。网关接收连接,然后自行建立与目标节点的连接。

1
为了让它更有趣一些: 代理是一种设计模式,而反向代理是一种架构模式。 - Bran

5
一个外观模式的主要价值在于'简化'内部组件(在外观背后)的使用。可能是因为外观中的一个入口点或函数将使用内部组件的多个函数。如果网关带来相同的'简化'API或其背后组件的使用,则可以视为外观。在其他情况下,网关可能仅是架构中的中间件、适配器、包装器或调用转发元素。或者网关可能穿着多个帽子,例如在简化一些流程、转发一些呼叫的同时,还充当身份验证或授权中间件。因此,在我看来,网关是一个高度抽象的模式,可以涵盖一个或多个特定的结构模式,例如外观、适配器、包装器、装饰器或中间件等。 Martin Fowler对网关的定义是狭窄的(至少这里),更接近于充当格式装饰器API网关
就实现而言,网关可以做任何事情,没有限制。它实际上是一个应用程序,并且可以提供任何功能。

2
回答您的问题,我认为Facade并不等同于Gateway,但是Facade≈Gateway。我的意思是它们大致相等,但是它们的区别根据上面不同的意见似乎不太清楚。
需要记住的一点是,设计模式和术语的关键组成部分之一是帮助更轻松地传达您的想法。因此,如果您总是使用facade这个术语进行交流,那么被理解的机会就更大,因为这个术语最常用。

2

门面模式用于将一些对象图像视为单个对象进行处理,而网关模式用于连接两个不同的模块/系统。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接