198

外观是一个包含许多其他类的类吗?

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

你能向我解释一下这个Facade模式吗?

4

21 回答 21

197

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

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

Facade 为用户屏蔽了系统的复杂细节,并为他们提供了其中的simplified view一个easy to use。它也是decouples从子系统的细节中使用系统的代码,使得以后修改系统更容易。

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

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

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

于 2011-03-09T07:09:43.510 回答
106

维基百科有一个很好的外观模式示例。

/* 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();
    }
}
于 2013-09-05T13:35:09.003 回答
44

如上一个答案中所述,它为消费客户端提供了一个简单的接口。例如:“watch ESPN”是预期的功能。但它涉及几个步骤,例如:

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

但是外观将简化这一点,只为客户端提供“观看 ESPN”功能。

于 2011-03-09T07:14:10.863 回答
30

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");
       }
  }
于 2013-12-14T09:52:03.997 回答
23

一个简短的解释:

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

试着理解有和没有 Façade 的场景:
如果你想把钱从 accout1 转移到 account2,那么要调用的两个子系统是,从 account1 提款和存款到 account2。

有和没有立面

于 2018-04-04T08:18:06.513 回答
11

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

于 2011-03-09T07:12:41.987 回答
9

关于您的查询:

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

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

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

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

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

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

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

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. 外观模式可以应用于任何开发点,通常是接口数量增加并且系统变得复杂时
  3. 子系统接口不知道 Facade,它们不应该有任何 Facade 接口的引用
  4. 外观模式应该应用于类似类型的接口,它的目的是提供一个接口而不是多个接口来完成类似的工作。

也可以查看sourcemaking文章以获得更好的理解。

于 2016-03-08T03:37:59.060 回答
6

外观模式是许多其他接口的包装器,以产生更简单的接口。

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

尝试阅读更多模式:

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

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

于 2011-03-09T07:11:47.377 回答
6

外观模式的另一种用途可能是减少团队的学习曲线。让我给你举个例子:

让我们假设您的应用程序需要利用 Excel 提供的 COM 对象模型与 MS Excel 进行交互。您的一位团队成员了解所有 Excel API,他在其上创建了一个 Facade,它满足了应用程序的所有基本场景。团队中的其他成员无需花时间学习 Excel API。团队可以在不了解实现场景的内部结构或所有 MS Excel 对象的情况下使用外观。是不是很棒?

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

于 2011-03-16T10:19:12.357 回答
6

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

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

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

让我们总结一下:

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

于 2018-07-31T13:39:01.093 回答
5

外观的另一个示例:假设您的应用程序连接到数据库并在 UI 上显示结果。您可以使用外观使您的应用程序可配置,如使用数据库或模拟对象运行。因此,您将对外观类进行所有数据库调用,它将读取应用程序配置并决定触发数据库查询或返回模拟对象。这种方式应用程序变得独立于数据库,以防数据库不可用。

于 2013-02-04T07:02:52.660 回答
5

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

于 2013-03-26T18:29:58.650 回答
4

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

于 2011-03-09T07:19:32.313 回答
4

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

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

于 2016-10-30T14:45:44.463 回答
3

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

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

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

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

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

于 2015-01-28T08:16:04.540 回答
3

它只是创建一个包装器来调用多个方法。你有一个A带有方法 and 的类和带有x()方法andy()B类。您想一次调用 x, y, z ,使用 Facade 模式来执行此操作,您只需创建一个 Facade 类并创建一个方法让我们说。您只需调用调用这些方法的外观类的包装方法(),而不是单独调用每个方法(x、y 和 z) 。k()z()xyz()xyz()

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

于 2019-01-06T03:16:03.307 回答
2

所有设计模式都是以某种方式排列的适合特定应用程序的一些类。外观模式的目的是隐藏一个或多个操作的复杂性。您可以从http://preciselyconcise.com/design_patterns/facade.php查看示例并学习外观模式

于 2014-05-09T17:06:29.833 回答
2

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

电影结束时会发生什么?你必须做同样的事情,但顺序相反,所以观看和结束电影的复杂性变得非常复杂。外观模式说你可以创建一个外观并让用户只调用一个方法而不是调用所有这些。让我们创建外观:

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 模式为子系统中的一组接口提供了统一的接口。Facade 定义了一个更高级别的接口,使子系统更易于使用。”

于 2020-10-01T17:35:54.150 回答
1

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

于 2014-07-10T06:47:53.570 回答
1

外观设计模式属于结构设计模式。简而言之,Facade 是指外观。这意味着在外观设计模式中,我们隐藏了一些东西,只显示客户实际需要的东西。阅读以下博客了解更多信息:http: //www.sharepointcafe.net/2017/03/facade-design-pattern-in-aspdotnet.html

于 2017-08-12T16:36:02.517 回答
1

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

于 2018-01-20T18:49:00.950 回答