什么是立面设计模式?

时间:2011-03-09 07:04:31

标签: design-patterns facade

facade 是一个包含很多其他类的类吗?

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

你能解释一下 Facade 模式吗?

20 个答案:

答案 0 :(得分:177)

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

Facade 设计模式简化了复杂系统的界面;因为它通常由构成复杂系统子系统的所有类组成。

Facade保护用户免受系统的复杂细节的影响,并为其提供simplified view easy to use的{​​{1}}。它还decouples从子系统的细节使用系统的代码,以便以后更容易修改系统。

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

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

此外,在学习设计模式时,重要的是能够识别哪种模式适合您的问题,然后适当地使用它。滥用模式或试图将其与某些问题相匹配是非常常见的,因为你知道它。使用设计模式学习\时要注意这些陷阱。

答案 1 :(得分:90)

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();
    }
}

答案 2 :(得分:40)

如前面的答案所述,它为消费客户提供了一个简单的界面。 例如:“观看ESPN”是预期的功能。但它涉及以下几个步骤:

  1. 如果需要,请打开电视;
  2. 检查卫星/电缆功能;
  3. 如果需要,请切换到ESPN。
  4. 但是外观将简化这一点,并且只为客户提供“观看ESPN”功能。

答案 3 :(得分:28)

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");
       }
  }

答案 4 :(得分:15)

一个简短而简单的解释:

  • Facade模式为一组接口提供统一的接口 在子系统中。
  • Facade定义了制作子系统的更高级别接口 更容易使用。

尝试使用和不使用Façade来理解场景:
如果您想将资金从accout1转移到account2,那么要调用的两个子系统将从account1退出并存入account2。

with and without facade

答案 5 :(得分:10)

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

答案 6 :(得分:7)

关于您的查询:

  

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

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

  

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

所有设计模式也是普通类。 @ Unmesh Kondolikar 正确回答了这个问题。

  

你能解释一下这个Facade,我是设计模式的新手。

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

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

Facade模式通常用于:

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

    本网站提供预订选项

    1. 航班
    2. 酒店
    3. 航班+酒店
    4. 代码段:

      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的书籍API内部调用子系统的API

        flightBooking.bookFlight
        trainBooking.bookTrain(info);
        hotelBooking.bookHotel(info);
        
      4. 通过这种方式,TravelFacade提供了更简单,更简单的API,无需暴露子系统API。

      5. 关键要点:(来自 Pankaj Kumar的journaldev文章

        1. 外观模式更像是客户端应用程序的 帮助
        2. Facade模式可以应用于任何开发点,通常是 ,当接口数量增加且系统完成时 x
        3. 子系统界面不知道Facade,他们 不应该有任何Facade接口的参考
        4. Facade模式应该应用于类似的接口 ,其目的是提供单个接口而不是多个接口来完成类似的工作
        5. 请查看sourcemaking文章,以便更好地理解。

答案 7 :(得分:6)

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

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

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

答案 8 :(得分:6)

Facade模式是结果中许多其他接口的包装器,以生成更简单的接口。

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

尝试阅读更多模式:

立面图案:http://www.dofactory.com/Patterns/PatternFacade.aspx#_self1

或更一般地说:http://www.dofactory.com/Patterns/Patterns.aspx

答案 9 :(得分:5)

Facade暴露了大多数被调用的简化函数,实现隐藏了客户本来必须处理的复杂性。一般来说,实现使用多个包,类和函数。良好的外观使得其他类的直接访问很少见。例如,当我访问ATM并提取一些金额时。 ATM隐藏它是直接进入自有银行还是通过协商网络进行外部银行。 ATM就像一个门面消耗多个设备和子系统,作为客户端我不必直接处理。

答案 10 :(得分:4)

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

答案 11 :(得分:4)

  

Facade是一个具有一定功能的类,位于工具包和完整的应用程序之间,可以简化包或子系统中类的使用。 Facade模式的目的是提供一个使子系统易于使用的接口。     - 从C#中的book设计模式中提取。

答案 12 :(得分:4)

  

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

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

答案 13 :(得分:4)

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

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

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

我们总结一下:

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

答案 14 :(得分:3)

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

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

当使用大量相互依赖的类或需要使用多种方法的类时,外观模式是理想的,特别是当它们使用复杂或难以理解时。 Facade类是一个&#34;包装器&#34;包含一组易于理解且易于使用的成员。这些成员代表facade用户访问子系统,隐藏了实现细节。

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

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

答案 15 :(得分:2)

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

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

答案 16 :(得分:2)

所有设计模式都是以某种方式排列的某些类,或者适合特定应用的其他类。 Facade模式的目的是隐藏操作或操作的复杂性。您可以查看示例并从http://preciselyconcise.com/design_patterns/facade.php

学习外观模式

答案 17 :(得分:1)

Facade模式为子系统接口组提供了统一的接口。 Facade定义了一个高级接口,简化了子系统的工作。

答案 18 :(得分:1)

它基本上是单窗口清关系统。你将委托任何工作委托给另一个班级的特定方法。

答案 19 :(得分:0)

我喜欢Eric Freeman, Elisabeth Freeman, Kathy Sierra, Bert Bates - Head First Design Patterns书中的一个例子。 例: 假设您创建了家庭影院,最后您想看电影。因此,您必须这样做:

        Amplifier amplifier = new Amplifier();
        CdPlayer cdPlayer = new CdPlayer();
        DvdPlayer dvdPlayer = new DvdPlayer();
        Lights lights = new Lights();
        PopcornPopper popcornPopper = new PopcornPopper();
        Projector projector = new Projector();
        Screen screen = new Screen();

        popcornPopper.turnOn();
        popcornPopper.pop();
        amplifier.turnOn();
        amplifier.setVolume(10);
        lights.turnOn();
        lights.dim(10);
        screen.up();
        dvdPlayer.turnOn();
        dvdPlayer.play();

电影结束后会发生什么?您必须执行相同的操作,但顺序相反,因此观看和结束电影的复杂性变得非常复杂。 Facade模式表示您可以创建一个Facade,让用户仅调用一个方法而不是全部调用。 让我们创建外观:

public class HomeTheatherFacade {
    Amplifier amplifier;
    DvdPlayer dvdPlayer;
    CdPlayer cdPlayer;
    Projector projector;
    Lights lights;
    Screen screen;
    PopcornPopper popcornPopper;

    public HomeTheatherFacade(Amplifier amplifier, DvdPlayer dvdPlayer, CdPlayer cdPlayer, Projector projector, Lights lights, Screen screen, PopcornPopper popcornPopper) {
    this.amplifier = amplifier;
    this.dvdPlayer = dvdPlayer;
    this.cdPlayer = cdPlayer;
    this.projector = projector;
    this.lights = lights;
    this.screen = screen;
    this.popcornPopper = popcornPopper;
}

public void watchMovie(String movieTitle) {
    popcornPopper.turnOn();
    popcornPopper.pop();
    amplifier.turnOn();
    amplifier.setVolume(10);
    lights.turnOn();
    lights.dim(10);
    screen.up();
    dvdPlayer.turnOn();
    dvdPlayer.play();
}

public void endMovie() {
    dvdPlayer.turnOff();
    screen.down();
    lights.turnOff();
    amplifier.turnOff();
}
}

现在,您可以仅调用watchMovieendMovie方法来代替调用所有这些方法:

public class HomeTheatherFacadeTest {
    public static void main(String[] args){
        Amplifier amplifier = new Amplifier();
        CdPlayer cdPlayer = new CdPlayer();
        DvdPlayer dvdPlayer = new DvdPlayer();
        Lights lights = new Lights();
        PopcornPopper popcornPopper = new PopcornPopper();
        Projector projector = new Projector();
        Screen screen = new Screen();
        
        HomeTheatherFacade homeTheatherFacade = new HomeTheatherFacade(amplifier, dvdPlayer, cdPlayer, projector, lights, screen, popcornPopper);
        homeTheatherFacade.watchMovie("Home Alone");
        homeTheatherFacade.endMovie();
    }
}

所以:

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