C# 設(shè)計(jì)模式:適配器模式(Adapter Pattern)
適配器模式是一種結(jié)構(gòu)型設(shè)計(jì)模式,它允許不兼容的接口之間能夠相互合作。這種模式涉及到一個(gè)單獨(dú)的類,它負(fù)責(zé)加入獨(dú)立的或不兼容的接口功能。簡單來說,適配器模式就是一個(gè)中間件,它使得原本由于接口不兼容而不能一起工作的類可以一起工作。
應(yīng)用場景
適配器模式通常應(yīng)用于以下情況:
- 當(dāng)你希望使用某個(gè)類,但是它的接口與其他代碼不兼容時(shí)。
- 當(dāng)你想創(chuàng)建一個(gè)可重用的類,該類可以與未知的或未來的類(即那些接口可能不兼容的類)協(xié)同工作。
- 當(dāng)你需要使用幾個(gè)現(xiàn)有的子類,但是子類化每個(gè)類以適配它們的接口會(huì)導(dǎo)致代碼可復(fù)用性降低時(shí)。
優(yōu)勢
- 提高類的復(fù)用性:通過適配器,可以使原本因接口不兼容而不能一起工作的類可以一起工作。
- 增加了類的透明性和靈活性:隱藏了具體實(shí)現(xiàn),用戶只需要關(guān)注接口。
- 系統(tǒng)的可擴(kuò)展性較好:在實(shí)現(xiàn)新的適配器時(shí),不必修改原有代碼,符合開閉原則。
劣勢
- 過多的使用適配器會(huì)使系統(tǒng)非常凌亂:不僅會(huì)產(chǎn)生很多小類,而且在維護(hù)時(shí)可能會(huì)造成困難。
- 不易于理解:尤其是涉及到多重適配時(shí),適配器的引入可能會(huì)讓系統(tǒng)的復(fù)雜性大大增加。
例子1:電源適配器
想象一下,我們有一個(gè)IUSPowerSource美國電源接口,它提供110V電壓,而我們有一個(gè)設(shè)備是IEUPowerDevice歐洲設(shè)備,它需要220V電壓。為了讓這個(gè)設(shè)備在美國使用,我們需要一個(gè)適配器。
首先,我們定義兩個(gè)接口:
public interface IUSPowerSource
{
int Provide110V();
}
public interface IEUPowerDevice
{
void PowerOn(int voltage);
}
兩個(gè)類:
public class EUPowerDevice : IEUPowerDevice
{
public void PowerOn(int voltage)
{
MessageBox.Show(voltage.ToString());
}
}
public class USPowerSource : IUSPowerSource
{
public int Provide110V()
{
return 110;
}
}
然后,我們實(shí)現(xiàn)一個(gè)適配器:
public class PowerAdapter: IUSPowerSource
{
private IEUPowerDevice _device;
public PowerAdapter(IEUPowerDevice device)
{
_device = device;
}
public int Provide110V()
{
// 適配器邏輯,將110V轉(zhuǎn)換為220V
int voltage110 = 110;
int voltage220 = Convert110VTo220V(voltage110);
_device.PowerOn(voltage220);
return voltage110;
}
private int Convert110VTo220V(int voltage110)
{
// 假設(shè)這里有復(fù)雜的轉(zhuǎn)換邏輯
return voltage110 * 2;
}
}
最后,使用適配器讓歐洲設(shè)備在美國電源上工作:
private void btnConvert_Click(object sender, EventArgs e)
{
IEUPowerDevice europeanDevice = new EUPowerDevice();
IUSPowerSource adapter = new PowerAdapter(europeanDevice);
var ret = adapter.Provide110V(); // 設(shè)備可以在110V電源上工作了
}
圖片
例子2:日志系統(tǒng)適配器
假設(shè)你有一個(gè)老舊的日志系統(tǒng),它只支持輸出日志到控制臺(tái),但是現(xiàn)在需要將日志輸出到文件中。我們可以通過適配器模式來實(shí)現(xiàn)這一需求,而不是修改原有的日志系統(tǒng)。
首先,定義日志接口:
public interface ILogger
{
void Log(string message);
}
舊的日志系統(tǒng)實(shí)現(xiàn):
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine("Log to console: " + message);
}
}
現(xiàn)在,我們需要一個(gè)適配器來實(shí)現(xiàn)文件日志功能:
public class FileLoggerAdapter : ILogger
{
private FileLogger _fileLogger;
public FileLoggerAdapter(FileLogger fileLogger)
{
_fileLogger = fileLogger;
}
public void Log(string message)
{
_fileLogger.WriteToFile(message);
}
}
public class FileLogger
{
public void WriteToFile(string message)
{
// 實(shí)現(xiàn)將消息寫入文件的邏輯
}
}
使用適配器輸出日志到文件:
ILogger logger = new FileLoggerAdapter(new FileLogger());
logger.Log("This is a log message."); // 現(xiàn)在日志被寫入到文件中