facade 外观设计模式是什么?

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

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

你能给我解释一下这个Facade 外观模式吗?

126700 次浏览

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

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

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

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

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

此外,在学习设计模式时,重要的是能够识别出适合给定问题的模式,然后适当地使用它。误用某个模式或仅仅因为知道某个模式就试图将其适用于某个问题,这是非常常见的事情。在学习使用设计模式时要注意这些陷阱。

facade模式是一个结果中许多其他接口的包装,以产生一个更简单的接口。

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

试着阅读更多的模式:

外观图案:http://www.dofactory.com/Patterns/PatternFacade.aspx#_self1

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

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

正如在前面的回答中所解释的,它为消费客户端提供了一个简单的接口。 例如:“观看ESPN”是预期功能。但它包含以下几个步骤:

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

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

facade是一个类,其功能级别介于工具包和完整应用程序之间,提供包或子系统中类的简化用法。Facade模式的目的是提供一个使子系统易于使用的接口。 ——在c#中提取设计模式

Façade模式的另一个用途是缩短团队的学习曲线。让我给你们举个例子:

让我们假设您的应用程序需要通过使用Excel提供的COM对象模型与MS Excel交互。你的一个团队成员知道所有的Excel api,他在上面创建了一个Facade,它满足应用程序的所有基本场景。团队中的其他成员不需要花时间学习Excel API。团队可以在不知道实现场景所涉及的内部或所有MS Excel对象的情况下使用facade。这不是很棒吗?

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

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

facade暴露了通常被调用的简化函数,而实现隐藏了客户端否则必须处理的复杂性。一般来说,实现中使用多个包、类和函数。编写良好的facade使得很少能直接访问其他类。例如,当我去自动取款机取钱时。自动取款机隐藏了它是直接流向自己的银行,还是通过协商好的网络流向外部银行。ATM就像一个门面,使用多个设备和子系统,作为客户,我不需要直接处理这些设备和子系统。

维基百科有一个很好的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();
}
}

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

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

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

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

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

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

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

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

关于您的疑问:

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

是的。它是应用中多个子系统的封装器。

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

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

你能给我解释一下这个立面吗?我对设计模式不熟悉。

根据GoF, 外观设计模式被定义为:

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

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

  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是大系统的不同子系统

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

    Flight Booking
    Train Booking
    Hotel Booking
    Flight + Hotel booking
    Train + Hotel booking
    
  3. book API from TravelFacade internally calls below APIs of sub-systems

    flightBooking.bookFlight
    trainBooking.bookTrain(info);
    hotelBooking.bookHotel(info);
    
  4. In this way, TravelFacade provides simpler and easier API with-out exposing sub-system APIs.

Key takeaways : ( from journaldev article by Pankaj Kumar)

  1. Facade pattern is more like a helper for client applications
  2. Facade pattern can be applied at any point of development, usually when the number of interfaces grow and system gets complex.
  3. Subsystem interfaces are not aware of Facade and they shouldn’t have any reference of the Facade interface
  4. Facade pattern should be applied for similar kind of interfaces, its purpose is to provide a single interface rather than multiple interfaces that does the similar kind of jobs

Have a look at sourcemaking article too for better understanding.

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

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

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

简短而简单的解释:

    Facade模式为一组接口提供了一个统一的接口 .在子系统中
  • Facade定义了一个更高级的接口,该接口使子系统

试着理解有和没有Façade的场景:
如果您想要将钱从account1转移到account2,那么需要调用的两个子系统是:从account1提取和存入account2。< / p >

with and without facade .

这个模式在现实生活中有一个很好的例子——汽车起动发动机

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

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

让我们总结一下:

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

它只是创建一个包装器来调用多个方法。 你有一个带有方法x()y()A类和带有方法k()z()B类。 你想要一次调用x, y, z,使用Facade模式来做到这一点,你只需要创建一个Facade类并创建一个方法,比如xyz()。 而不是分别调用每个方法(x,y和z),您只需调用调用这些方法的facade类的包装器方法(xyz())

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

我喜欢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定义了一个更高级别的接口 使子系统更容易使用。"