外觀(門面)模式
外觀模式(Facade),他隱藏了系統的復雜性,并向客戶端提供了一個可以訪問系統的介面,這種型別的設計模式屬于結構性模式,為子系統中的一組介面提供了一個統一的訪問介面,這個介面使得子系統更容易被訪問或者使用,類似的實際例子有訊息中間件,把一個資料丟到訊息中間件,誰需要,誰去訊息后中間件去拿,這種設計模式可以用于解耦,
我們舉個栗子,你要去工廠制造一輛汽車,你需要先從門口去一樓制造引擎,再從門口去二樓制造底盤,最后從門口去五樓制造變速箱,然后去四樓制造輪胎,這樣整個流程會特別繁瑣,外觀模式就提供一個門面介面(Facade),門面內把原來的邏輯流程進行封裝,你只需要從門口去到這個門面,門面內部分工幫你去管理汽車的制造流程,回歸代碼世界,如果我們不使用門面模式,需要呼叫發動機制造的物件、底盤制造的物件變速箱制造的物件等等,這樣你的業務邏輯便顯得雜亂無章并且代碼各個子系統之間的耦合度很高,顯然這樣做不是最優方案,

門面解決方案:
將汽車制造流程邏輯進行封裝,只提供一個汽車制造介面,當客戶訪問汽車介面(Facade)時,工廠內部流水線制造組裝完成一輛用戶所需的汽車,這樣做的優點就是:把多個物件之間的呼叫互動變為一個物件與一個介面之間的互動,降低代碼耦合度,與用戶分別呼叫子系統模塊相比,客戶不能自己定義引擎、底盤等配件的型號,所以門面模式提供的功能有限,但是它可以快速且簡便的提供客戶真正關心的需求,

talk is cheaper,show me your code.
假設我們有一個需求:將ogg格式的視頻檔案轉換為mp4格式,那么我們需要讀取ogg格式的檔案流,將流轉換為音頻流、視頻流,寫入檔案,再進行音頻流、視頻流組合,最后完成轉換,當然我們可以單個流程進行呼叫,下面的代碼中有兩種方式的具體體現,
代碼已經開源至Github
https://github.com/FirstMrRight/Design_pattern
Codec.java
/**
* @author Liutx
* @date 2020/12/26 22:37
* @Description 解碼器介面
*/
public interface Codec {
}
MPEG4CompressionCodec.java
/**
* @author Liutx
* @date 2020/12/26 22:38
* @Description MPEG4解碼器
*/
public class MPEG4CompressionCodec implements Codec {
/**
* 該解碼器能夠行使的功能
*/
public String type = "mp4";
}
OggCompressionCodec.java
/**
* @author Liutx
* @date 2020/12/26 22:40
* @Description ogg解碼器
*/
public class OggCompressionCodec implements Codec {
public String type = "ogg";
}
BitrateReader.class
/**
* @author Liutx
* @date 2020/12/26 22:48
* @Description 位元組讀取轉換為Video
*/
public class BitrateReader {
public static VideoFile read(VideoFile file, Codec codec) {
System.out.println("BitrateReader: reading file...");
return file;
}
public static VideoFile convert(VideoFile buffer, Codec codec) {
System.out.println("BitrateReader: writing file...");
return buffer;
}
}
AudioMixer.java
/**
* @author Liutx
* @date 2020/12/26 22:50
* @Description 混音器,組合視頻、音頻
*/
public class AudioMixer {
public File fix(VideoFile result){
System.out.println("AudioMixer: fixing audio...");
return new File("tmp");
}
}
VideoFile.java
/**
* @author Liutx
* @date 2020/12/26 22:33
* @Description
*/
public class VideoFile {
private String name;
private String codecType;
public VideoFile(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCodecType() {
return codecType;
}
public void setCodecType(String codecType) {
this.codecType = codecType;
}
}
VideoConversionFacade.java
/**
* @author Liutx
* @date 2020/12/26 22:58
* @Description 門面模式封裝內部流程、對外提供介面
*/
public class VideoConversionFacade {
public File convertVideo(String fileName, String format) {
System.out.println("VideoConversionFacade: conversion started.");
VideoFile file = new VideoFile(fileName);
Codec sourceCodec = CodecFactory.extract(file);
Codec destinationCodec;
if (format.equals("mp4")) {
destinationCodec = new OggCompressionCodec();
} else {
destinationCodec = new MPEG4CompressionCodec();
}
VideoFile buffer = BitrateReader.read(file, sourceCodec);
VideoFile intermediateResult = BitrateReader.convert(buffer, destinationCodec);
File result = (new AudioMixer()).fix(intermediateResult);
System.out.println("VideoConversionFacade: conversion completed.");
return result;
}
}
ClientDemo.java (呼叫)
public class ClientDemo {
public static void main(String[] args) {
VideoConversionFacade converter = new VideoConversionFacade();
File mp4Video = converter.convertVideo("video.ogg", "mp4");
System.out.println("===================================");
VideoFile file = new VideoFile("video.ogg");
CodecFactory.extract(file);
BitrateReader.read(file,new OggCompressionCodec());
BitrateReader.convert(file,new MPEG4CompressionCodec());
AudioMixer audioMixer = new AudioMixer();
audioMixer.fix(file);
}
}
Console 輸出:
VideoConversionFacade: conversion started.
CodecFactory: extracting ogg audio...
BitrateReader: reading file...
BitrateReader: writing file...
AudioMixer: fixing audio...
VideoConversionFacade: conversion completed.
===================================
CodecFactory: extracting ogg audio...
BitrateReader: reading file...
BitrateReader: writing file...
AudioMixer: fixing audio...
總結:
使用門面模式可以非常優雅的實作代碼的呼叫,當然我們也可以自己使用單獨呼叫物件的方式實作相同的功能,但是這種方式不僅顯得代碼雜亂無章,而且這種方式一看就非常不環保,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/241437.html
標籤:其他
上一篇:Design twelve
