??最近準(zhǔn)備好好研究下Retrifot的源代碼 , 因?yàn)镽etrofit的主要業(yè)務(wù)用到了外觀模式,正好以前沒有仔細(xì)研究過這種設(shè)計(jì)模式瞭稼,同時(shí)也是為了降低研究Retrofit源碼的難度杉畜,所以做下關(guān)于外觀設(shè)計(jì)模式的功課湿弦。為了方便看官理解裁良,無關(guān)的代碼部分盡可能的使用了偽代碼凿将。
??進(jìn)入正題 , 軟件開發(fā)中時(shí)常出現(xiàn),需要與多個(gè)復(fù)雜子系統(tǒng)進(jìn)行交互的情況趴久,倘若直接與各個(gè)子系統(tǒng)進(jìn)行交互必定會(huì)出現(xiàn)較高的耦合性丸相。如果存在某一個(gè)中間對(duì)象專門負(fù)責(zé)與各個(gè)子系統(tǒng)進(jìn)行交互搔确,而第三方只需要與該中間對(duì)象交互即可彼棍,這便是外觀模式的由來。
??如上圖,沒有使用外觀模式之前膳算,各個(gè)系統(tǒng)之間的交互的復(fù)雜性座硕,而使用了外觀模式后,使用Facade中間對(duì)象與各個(gè)子系統(tǒng)進(jìn)行交互涕蜂,整個(gè)系統(tǒng)的耦合性一下就降低了华匾。
標(biāo)準(zhǔn)外觀模式:
??外觀模式中所指的子系統(tǒng)是一個(gè)廣義的概念,它可以是一個(gè)類机隙、一個(gè)功能模塊蜘拉、系統(tǒng)的一個(gè)組成部分或者一個(gè)完整的系統(tǒng)。子系統(tǒng)類通常是一些業(yè)務(wù)類有鹿,實(shí)現(xiàn)了一些具體的旭旭、獨(dú)立的業(yè)務(wù)功能。
??以文件加解密為例上實(shí)例代碼葱跋,文件加解密可以分為三個(gè)模塊持寄, 讀取文件源梭,加解密文件,寫入文件稍味。其UML圖如下:
class FileReader
{
public string Read(string fileNameSrc)
{
......
}
}
class CipherMachine
{
public string Encrypt(string plainText)
{
Console.Write("數(shù)據(jù)加密废麻,將明文轉(zhuǎn)換為密文:");
......
return es;
}
class FileWriter
{
public void Write(string encryptStr,string fileNameDes)
{
......
}
}
重點(diǎn)在EncryptFacade上,用于與各個(gè)子系統(tǒng)進(jìn)行直接交互.
class EncryptFacade
{
//維持對(duì)其他對(duì)象的引用
private FileReader reader;
private CipherMachine cipher;
private FileWriter writer;
public EncryptFacade()
{
reader = new FileReader();
cipher = new CipherMachine();
writer = new FileWriter();
}
//調(diào)用其他對(duì)象的業(yè)務(wù)方法
public void FileEncrypt(string fileNameSrc, string fileNameDes)
{
string plainStr = reader.Read(fileNameSrc);
string encryptStr = cipher.Encrypt(plainStr);
writer.Write(encryptStr, fileNameDes);
}
}
class Program
{
static void Main(string[] args)
{
EncryptFacade ef = new EncryptFacade();
ef.FileEncrypt("src.txt", "des.txt");
Console.Read();
}
}
抽象外觀模式
??在標(biāo)準(zhǔn)的外觀模式中模庐,如果需要增加烛愧、刪除或更換與外觀類交互的子系統(tǒng)類,必須修改外觀類或客戶端的源代碼赖欣,這將違背開閉原則屑彻,因此可以通過引入抽象外觀類來對(duì)系統(tǒng)進(jìn)行改進(jìn),在一定程度上可以解決該問題顶吮。
??在引入抽象外觀類之后社牲,客戶端可以針對(duì)抽象外觀類進(jìn)行編程,對(duì)于新的業(yè)務(wù)需求悴了,不需要修改原有外觀類搏恤,而對(duì)應(yīng)增加一個(gè)新的具體外觀類,由新的具體外觀類來關(guān)聯(lián)新的子系統(tǒng)對(duì)象湃交,同時(shí)通過修改配置文件來達(dá)到不修改任何源代碼并更換外觀類的目的熟空。
??如,現(xiàn)在我們不滿意原有的那種加解密方式了,想要使用一種新的加解密方式替代搞莺。
??使用抽象外觀模式更改后的UML圖.
??其中,FileReader和FileWriter使用的仍然是之前的類息罗,這里只不過是增加了一個(gè)新的加解密類NewCipherMachine,一個(gè)新的中間對(duì)象NewEncryptFacade,一個(gè)抽象類AbstractEncryptFacade.
abstract class AbstractEncryptFacade
{
public abstract void FileEncrypt(string fileNameSrc, string fileNameDes);
}
class NewEncryptFacade extends AbstractEncryptFacade
{
private FileReader reader;
private NewCipherMachine cipher;
private FileWriter writer;
public NewEncryptFacade()
{
reader = new FileReader();
cipher = new NewCipherMachine();
writer = new FileWriter();
}
public override void FileEncrypt(string fileNameSrc, string fileNameDes)
{
string plainStr = reader.Read(fileNameSrc);
string encryptStr = cipher.Encrypt(plainStr);
writer.Write(encryptStr, fileNameDes);
}
}
class NewCipherMachine
{
public string Encrypt(string plainText)
{
Console.Write("數(shù)據(jù)加密才沧,將明文轉(zhuǎn)換為密文:");
迈喉。。温圆。挨摸。。岁歉。
return es;
}
}
這里使用配置文件得运,通過在代碼中選擇加載配置文件,從而使用對(duì)應(yīng)的Facade對(duì)象锅移,以此來調(diào)用不同的加解密類熔掺。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="facade" value="FacadeSample.NewEncryptFacade"/>
</appSettings>
</configuration>
class Program
{
static void Main(string[] args)
{
AbstractEncryptFacade ef; //針對(duì)抽象外觀類編程
//讀取配置文件
string facadeString = ConfigurationManager.AppSettings["facade"];
//反射生成對(duì)象
ef = (AbstractEncryptFacade)。非剃。置逻。。努潘。诽偷。(facadeString);
ef.FileEncrypt("src.txt", "des.txt");
Console.Read();
}
}
總結(jié):
??自我感覺坤学,即便是抽象外觀模式,做的還是不夠好报慕,
每次要增加一個(gè)新的功能或者方法時(shí)深浮,就需要增加一個(gè)新的功能類以及一個(gè)新的中間Facade類,雖然通過配置文件可以選擇調(diào)用不同的功能類,但是感覺還是不夠眠冈。