文章来源:https://www.cnblogs.com/lthIU/p/5860607.html 文章内容有所改动
针对外观模式,即门面模式,在项目开发和实际应用中十分频繁,但是其极易理解,下面就简要介绍一下。
一:概念介绍
外观模式(Facade),他隐蔽了系统的复杂性,并向客户端提供了一个访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。
简单来说,该模式就是把一些复杂的流程封装成一个接口供外部用户更简单的使用。这个模式中,涉及到3个角色。
a.门面角色:外观模式的核心。它被客户角色调用,它熟悉子系统的功能。内部根据客户角色的需求预定了几种功能的组合。
b.子系统角色:实现了子系统的功能。它对客户角色和Facade是未知的。它内部可以有系统内的相互交互,也可以由供外界调用的接口。
c.客户角色:通过调用Facade来完成要实现的功能。
使用场景:
a.为复杂的模块或子系统提供外界访问的模块。
b.子系统互相独立。
c.在层析结构中,可以使用外观模式定义系统的每一层的入口。
三,实例
下面,我们就通过一个简单的例子来实现该模式。
每个Computer都有CPU,Memory,Disk。在Computer开启和关闭的时候,相应的部件也会开启和关闭,所以,使用了该外观模式后,会使用户和部件之间解耦。如:
看下示例程序。
package com.wpw.iteratorpro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CPU {
public static final Logger logger = LoggerFactory.getLogger(CPU.class);
public void start(){
logger.info("cpu is start ...");
}
public void shutdown(){
logger.info("cpu is shutdown ...");
}
}
上面是CPU类定义的方法和功能实现,这里仅为了简短说明便于理解。
package com.wpw.iteratorpro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author pc
*/
public class Disk {
private static final Logger logger=LoggerFactory.getLogger(Disk.class);
public void start(){
logger.info("disk is start ...");
}
public void shutdown(){
logger.info("disk is shutdown ...");
}
}
上面是Disk类定义的方法和功能实现,这里仅为了简短说明便于理解。
package com.wpw.iteratorpro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Memory {
public static final Logger logger=LoggerFactory.getLogger(Memory.class);
public void start(){
logger.info("memory is start ...");
}
public void shutdown(){
logger.info("memory is shutdown ...");
}
}
上面是Memory类定义的方法和功能实现,这里仅为了简短说明便于理解。
下面就是客户端调用门面类的接口了。
package com.wpw.iteratorpro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author pc
*/
public class Computer {
private static final Logger logger = LoggerFactory.getLogger(Computer.class);
private CPU cpu;
private Memory memory;
private Disk disk;
private volatile Boolean flag;
public Computer() {
cpu = new CPU();
memory = new Memory();
disk = new Disk();
}
public void start() {
logger.info("computer start begin ...");
cpu.start();
memory.start();
disk.start();
logger.info("computer start end ...");
flag = true;
}
public void shutdown() {
if (!flag) {
throw new NullPointerException();
}
logger.info("computer shutdown begin ...");
cpu.shutdown();
memory.shutdown();
disk.shutdown();
logger.info("computer shutdown end ...");
}
}
写一个测试类进行测试一下。
package com.wpw.iteratorpro;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author pc
*/
public class FacadeTest {
private static final Logger logger = LoggerFactory.getLogger(FacadeTest.class);
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Computer computer = new Computer();
computer.start();
logger.info("1-------------------------------1");
computer.shutdown();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
Computer computer = new Computer();
computer.start();
logger.info("2-------------------------------2");
computer.shutdown();
}
});
thread.start();
thread.setName("ThreadA-");
thread2.start();
thread2.setName("ThreadB-");
Runtime.getRuntime().addShutdownHook(new Thread(() -> logger.info("main thread end ...")));
}
}
我们看下控制台的输出内容,看下是否符合门面模式的使用。
[ThreadA-] INFO com.wpw.iteratorpro.Computer - computer start begin ...
[ThreadA-] INFO com.wpw.iteratorpro.CPU - cpu is start ...
[ThreadA-] INFO com.wpw.iteratorpro.Memory - memory is start ...
[ThreadA-] INFO com.wpw.iteratorpro.Disk - disk is start ...
[ThreadA-] INFO com.wpw.iteratorpro.Computer - computer start end ...
[ThreadA-] INFO com.wpw.iteratorpro.FacadeTest - 1-------------------------------1
[ThreadA-] INFO com.wpw.iteratorpro.Computer - computer shutdown begin ...
[ThreadA-] INFO com.wpw.iteratorpro.CPU - cpu is shutdown ...
[ThreadA-] INFO com.wpw.iteratorpro.Memory - memory is shutdown ...
[ThreadA-] INFO com.wpw.iteratorpro.Disk - disk is shutdown ...
[ThreadA-] INFO com.wpw.iteratorpro.Computer - computer shutdown end ...
[ThreadB-] INFO com.wpw.iteratorpro.Computer - computer start begin ...
[ThreadB-] INFO com.wpw.iteratorpro.CPU - cpu is start ...
[ThreadB-] INFO com.wpw.iteratorpro.Memory - memory is start ...
[ThreadB-] INFO com.wpw.iteratorpro.Disk - disk is start ...
[ThreadB-] INFO com.wpw.iteratorpro.Computer - computer start end ...
[ThreadB-] INFO com.wpw.iteratorpro.FacadeTest - 2-------------------------------2
[ThreadB-] INFO com.wpw.iteratorpro.Computer - computer shutdown begin ...
[ThreadB-] INFO com.wpw.iteratorpro.CPU - cpu is shutdown ...
[ThreadB-] INFO com.wpw.iteratorpro.Memory - memory is shutdown ...
[ThreadB-] INFO com.wpw.iteratorpro.Disk - disk is shutdown ...
[ThreadB-] INFO com.wpw.iteratorpro.Computer - computer shutdown end ...
[Thread-2] INFO com.wpw.iteratorpro.FacadeTest - main thread end ...
Process finished with exit code 0
从上面的实例来看,有了这个Facade类,也就是Computer类,用户就不用亲自调用子系统中的Disk,Memory,CPU类了,不需要知道系统内部的实现细节,甚至都不用知道系统内部的构成。客户端只需要跟Facade交互就可以了。
门面模式的优点:
a.松散耦合:使得客户端和子系统之间解耦,让子系统内部的模块功能更容易扩展和维护。
b.简单易用:客户端根本不需要知道子系统内部的实现,或者根本不需要知道子系统内部的构成,它只需要跟Facade类交互即可。
c.更好的划分访问层次:有些方法是系统内部相互交互的使用的。子系统把哪些暴露给外部的功能集中到门面中,这样就可以实现客户端的使用,很好的隐藏了子系统内部额细节。门面模式到这里就结束了,喜欢文章的可以转发文章。