外墙设计模式是什么?


191

门面是否是包含许多其他类的类?

是什么使它成为设计模式?对我来说,这就像一堂普通的课。

您能向我解释这种门面模式吗?


7
每个设计模式在其实现中都有很多类。
Felix Kling

1
外墙模式通过将多个接口隐藏在一个类中来创建易于使用的接口。本文有更多详细信息
user3199690 '02

在这篇文章中很好地解释了程序员
zdojo.com/java-tutorials/…– rishi007bansod

之所以对此表示
反对,

1
@RoyTruelove,做你想做的。只要有支持该问题的答案,就不会在乎。这个问题有什么支持的答案吗?
凯文(Kevin)

Answers:


190

设计模式是解决重复出现问题的常用方法。所有设计模式中的类都是普通类。重要的是它们的结构以及如何以最佳方式解决特定问题。

外观设计图案简化了接口到一个复杂的系统; 因为它通常由组成复杂系统子系统的所有类组成。

外观可以使用户免受系统复杂细节的影响,并为他们提供的simplified vieweasy to use。它还是decouples从子系统详细信息中使用系统的代码,使以后修改系统更加容易。

http://www.dofactory.com/Patterns/PatternFacade.aspx

http://www.blackwasp.co.uk/Facade.aspx

另外,学习设计模式时重要的是能够识别出适合您给定问题的模式,然后适当地使用它。仅仅因为您知道某种模式而滥用模式或试图使其适应某些问题是很常见的事情。在学习\使用设计模式时要注意这些陷阱。


9
@kevin:知道何时使用它们是最困难的部分。从理论上讲,模式可能很容易,但在实践中很难。您只能从中获得经验,即。编码,编码,编码。
菲利克斯·克林

外观设计模式也用于隐藏细节类工具并安全地提供公共api。
yebw

29
jQuery中的$只是外观设计模式的简单示例,它提供了简单的界面并隐藏了所有复杂性
Ajay Beniwal

对于一些寻找具有真实世界示例的外观设计模式的人。我遇到了这个简短的YouTube教程。希望它对您有用。your
tutorial /

当应用程序变得更大时,我们可以在单个系统上拥有多个外墙层吗?
Jeeva Jsb

99

Wikipedia有一个很好的Facade模式示例。

/* 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 ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

6
这是一个很好的例子。如果客户选择,则客户必须能够将外观中的所有步骤拼凑起来,私有方法不应隐藏任何内容。
罗布

2
恕我直言,这不是一个好例子,因为它不强调用例。正如TO所说,该示例仅显示了一个常规类。与硬件的关联是一种组合。对于Wiki上的示例而言,可能有些大材小用,但是使用依赖注入而不是实例化子模块将强调目的,并可能避免TO的混乱。
ManuelSchneid3r

这是一个了不起的示例,因为它只是将成千上万个单词包装在一起以了解概念本身。剩下的只是一个人可以拥有的不同方案的细节(当然,一种设计模式永远无法涵盖每个方案)。
Syed

41

如前面的答案中所述,它为使用方客户端提供了一个简单的界面。例如:“ watch ESPN”是预期的功能。但这涉及几个步骤,例如:

  1. 如果需要,请打开电视;
  2. 检查卫星/电缆功能;
  3. 如果需要,请切换到ESPN。

但是外观将简化此过程,仅向客户端提供“监视ESPN”功能。


29

Facade隐藏了系统的复杂性,并提供了到客户端的接口,客户端可以从该接口访问系统。

public class Inventory {
public String checkInventory(String OrderId) {
    return "Inventory checked";
}
}

public class Payment {
public String deductPayment(String orderID) {
    return "Payment deducted successfully";
}
}


public class OrderFacade {
private Payment pymt = new Payment();
private Inventory inventry = new Inventory();

public void placeOrder(String orderId) {
    String step1 = inventry.checkInventory(orderId);
    String step2 = pymt.deductPayment(orderId);
    System.out
            .println("Following steps completed:" + step1
                    + " & " + step2);
   }
}

public class Client {
       public static void main(String args[]){
         OrderFacade orderFacade = new OrderFacade();
         orderFacade.placeOrder("OR123456");
         System.out.println("Order processing completed");
       }
  }

是否允许子系统之间相互通信而不经过OrderFacade?在您的示例中,介于Payment和之间Inventory
Isuru

19

简短说明:

  • 外观模式为子系统中的一组接口提供了统一的接口。
  • Facade定义了一个更高级别的界面,使子系统更易于使用。

尝试了解带有和不带有Façade的情况:
如果要将钱从accout1转移到account2,则要调用的两个子系统是从account1提取并存入account2。

有无正面


简单明了的说明和示例,谢谢!您能否解释一下定义子系统的内容?当子系统可能包含相对不相关的子类/函数时,您的定义几乎适用于任何类。子系统的类是否必须紧密相关(例如,形成一个模块或一个库),以便可以将立面称为立面?
本尼

@Benni是的,子系统(可能是一个类)可能包含相对不相关的函数,但是Facade是一个类,您可以在其中确定要调用的特定函数。您要预订“旅行套票”,在一个地方/一个表单中选择酒店,出租车,航班,然后在内部外观调用不同的适当类的功能并返回最终结果。是不是
阿伦·拉伊

10

外墙不应描述为包含许多其他类的类。实际上,它是此类的接口,应使类的使用更加容易,否则,facade类将无用。


7

关于您的查询:

Facade是一个包含很多其他课程的课程吗?

是。它是应用程序中许多子系统的包装。

是什么使它成为设计模式?对我来说,就像是普通班

所有设计模式也都是常规类。@ Unmesh Kondolikar正确回答了该查询。

您能为我解释一下这个Facade吗?我是设计模式的新手。

根据GoF, Facade设计模式的定义为:

为子系统中的一组接口提供统一的接口。外观模式定义了一个更高级别的界面,该界面使子系统更易于使用

在以下情况下通常使用Facade模式:

  1. 需要一个简单的界面来访问复杂的系统。
  2. 子系统的抽象和实现紧密耦合。
  3. 需要一个分层软件的每个级别的入口点。
  4. 系统非常复杂或难以理解。

让我们以cleartrip的真实例子为例网站。

该网站提供预订选项

  1. 航班
  2. 饭店
  3. 机票+酒店

程式码片段:

import java.util.*;

public class TravelFacade{
    FlightBooking flightBooking;
    TrainBooking trainBooking;
    HotelBooking hotelBooking;

    enum BookingType {
        Flight,Train,Hotel,Flight_And_Hotel,Train_And_Hotel;
    }; 

    public TravelFacade(){
        flightBooking = new FlightBooking();
        trainBooking = new TrainBooking();
        hotelBooking = new HotelBooking();        
    }
    public void book(BookingType type, BookingInfo info){
        switch(type){
            case Flight:
                // book flight;
                flightBooking.bookFlight(info);
                return;
            case Hotel:
                // book hotel;
                hotelBooking.bookHotel(info);
                return;
            case Train:
                // book Train;
                trainBooking.bookTrain(info);
                return;
            case Flight_And_Hotel:
                // book Flight and Hotel
                flightBooking.bookFlight(info);
                hotelBooking.bookHotel(info);
                return;
             case Train_And_Hotel:
                // book Train and Hotel
                trainBooking.bookTrain(info);
                hotelBooking.bookHotel(info);
                return;                
        }
    }
}
class BookingInfo{
    String source;
    String destination;
    Date    fromDate;
    Date     toDate;
    List<PersonInfo> list;
}
class PersonInfo{
    String name;
    int       age;
    Address address;
}
class Address{

}
class FlightBooking{
    public FlightBooking(){

    }
    public void bookFlight(BookingInfo info){

    }
}
class HotelBooking{
    public HotelBooking(){

    }
    public void bookHotel(BookingInfo info){

    }
}
class TrainBooking{
    public TrainBooking(){

    }
    public void bookTrain(BookingInfo info){

    }
}

说明:

  1. FlightBooking, TrainBooking and HotelBooking 是大型系统的不同子系统: TravelFacade

  2. TravelFacade 提供一个简单的界面来预订以下选项之一

    Flight Booking
    Train Booking 
    Hotel Booking
    Flight + Hotel booking 
    Train + Hotel booking
    
  3. 来自TravelFacade的book API在子系统的API下面内部调用

    flightBooking.bookFlight
    trainBooking.bookTrain(info);
    hotelBooking.bookHotel(info);
    
  4. 这样,TravelFacade提供了越来越简单的API,而没有暴露子系统API。

关键要点:(摘自Pankaj Kumar的journaldev文章)

  1. 外观模式更像是一个助手客户端应用程序
  2. 外观模式可以在发展的任何点应用,通常在接口的数量增长和系统得到COMPLE X
  3. 子系统接口不了解Facade,因此不应具有Facade接口的任何引用
  4. 外墙模式应应用于类似类型的接口,其目的是提供一个单一的接口,而不是提供多个执行类似类型工作的接口

也可以参阅源制作文章,以更好地理解。


6

外观模式是许多其他接口的包装,从而产生了一个更简单的接口。

设计模式非常有用,因为它们可以解决重复出现的问题,并且通常可以简化代码。在一个同意使用相同模式的开发人员团队中,在维护彼此的代码时,它可以提高效率和理解。

尝试阅读更多模式:

外墙样式: http //www.dofactory.com/Patterns/PatternFacade.aspx#_self1

或更笼统:http : //www.dofactory.com/Patterns/Patterns.aspx


nileshgule.com/2012/07/facade-design-pattern.html我试图在这里以房屋贷款验证过程为例来描述Facade设计模式。
Nilesh Gule 2012年

6

Façade模式的另一种用途可能是减少团队的学习曲线。让我举一个例子:

让我们假设您的应用程序需要通过利用Excel提供的COM对象模型与MS Excel进行交互。您的团队成员之一了解所有Excel API,并在此基础上创建了一个Facade,它可以满足应用程序的所有基本情况。团队中的其他成员无需花时间学习Excel API。团队可以使用立面而无需了解内部场景或实现场景所涉及的所有MS Excel对象。不好吗?

因此,它在复杂子系统的顶部提供了简化且统一的界面。


5

外观的另一个示例:说您的应用程序连接到数据库并在UI上显示结果。您可以使用Facade使您的应用程序可配置,例如在使用数据库或模拟对象运行时。因此,您将对Facade类进行所有数据库调用,它将在其中读取app config并决定触发数据库查询或返回模拟对象。这样,在数据库不可用的情况下,应用程序将独立于数据库。


5

外观公开了通常称为的简化功能,而实现则掩盖了客户必须处理的复杂性。通常,实现在其中使用多个包,类和函数。写得好的外观使得很少可以直接访问其他类。例如,当我访问自动提款机并取款时。ATM隐藏它是直接进入自己的银行,还是通过协商的网络进入外部银行。ATM就像一个外墙,消耗多个设备和子系统,作为客户端,我不必直接处理这些设备和子系统。


5

该模式有一个很好的现实示例- 汽车起动机引擎

作为驾驶员,我们只需打开钥匙,汽车便会启动。尽可能简单。在幕后,涉及许多其他汽车系统(例如电池,引擎,燃料等),以使汽车成功启动,但它们隐藏在启动器之后。

如您所见,汽车启动器是Facade。它为我们提供了易于使用的界面,而无需担心所有其他汽车系统的复杂性。

让我们总结一下:

Facade模式简化并隐藏了大型代码块或API的复杂性,从而提供了一个更干净,易于理解且易于使用的界面。


4

外观是具有某种功能级别的类,位于工具包和完整的应用程序之间,可简化包或子系统中类的使用。Facade模式的目的是提供一个使子系统易于使用的接口。-摘录自 C#中的书《设计模式》。


4

Facade讨论了将复杂的子系统封装在单个接口对象中。这减少了成功利用子系统所需的学习曲线。它还促进了将子系统与其潜在的许多客户分离。另一方面,如果Facade是子系统的唯一访问点,它将限制“高级用户”可能需要的功能和灵活性。

资料来源:https : //sourcemaking.com/design_patterns/facade


3

设计模式是在软件设计中给定上下文中对常见问题的通用可重用解决方案。

外观设计模式是一种结构模式,因为它定义了在类或实体之间创建关系的方式。外墙设计模式用于定义到更复杂子系统的简化接口。

当使用大量相互依赖的类或需要使用多种方法的类时,尤其是当它们使用复杂或难以理解时,外观模式是理想的选择。Facade类是一个“包装器”,其中包含一组易于理解且易于使用的成员。这些成员代表外观用户访问子系统,从而隐藏实现细节。

当包装子系统设计不佳但由于源代码不可用或现有接口被广泛使用而无法重构的子系统时,外观设计模式特别有用。有时,您可能决定实现多个外观,以提供用于不同目的的功能子集。

外观模式的一个示例用法是将网站与业务应用程序集成。现有软件可能包含必须以特定方式访问的大量业务逻辑。该网站可能仅需要对此业务逻辑的有限访问。例如,网站可能需要显示待售商品是否已达到有限的库存水平。Facade类的IsLowStock方法可以返回一个布尔值来表明这一点。在后台,此方法可能隐藏了处理当前实物库存,进货库存,已分配物料以及每种物料的低库存水平的复杂性。



2

它只是创建一个包装来调用多个方法。您有一个方法x()和y()的A类,以及方法k()和z()的B类。您想一次调用x,y,z,使用Facade模式可以做到这一点,您只需创建一个Facade类并创建一个方法,例如xyz()。无需单独调用每个方法(x,y和z),您只需调用立面类的包装方法(xyz())即可。

类似的模式是存储库,但是它主要用于数据访问层。


1

它基本上是单窗口清除系统。您分配它将委托给另一类中的特定方法的任何工作。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.