認識Proxy Pattern
Proxy Pattern(代理模式):
是常見的設計模式之一,一般在中大系統要引用第三方控件時,會使用Proxy Pattern,主要用來隔離呼叫端及目的端,降低呼叫端及目的端的相依性,提升程式的可變性及延展性。
一般我們需要讀取外部檔案且Json序列化或反序列化,下列程式碼,直接相依Newtonsoft.Json的JsonConvert.DeserializeObject,當需要更換Text.Json或是其他套件時,可能就需要改動專案很多地方。
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
try
{
var path = $"{AppDomain.CurrentDomain.BaseDirectory}/Myfile.txt";
using (var r = new StreamReader(path))
{
//相依Newtonsoft.Json
foreach (var item in JsonConvert.DeserializeObject<IEnumerable<MyClass>>(r.ReadToEnd()))
{
Console.WriteLine(item.Name);
Console.WriteLine(item.Age);
Console.WriteLine("=============");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
public class MyClass
{
public string Name { get; set; }
public string Age { get; set; }
}
}
這時會新建一層中介層(Proxy Pattern)來降低呼叫端及目的端的相依性。
JsonParseProxy.cs:
namespace JsonParseProxy
{
public class JsonParseProxy
{
private string fileName;
public JsonParseProxy(string fileName)
{
this.fileName = fileName;
}
public IEnumerable<T> Load<T>()
{
try
{
using (var r = new StreamReader(fileName))
{
return JsonConvert.DeserializeObject<IEnumerable<T>>(r.ReadToEnd());
}
}
catch (IOException ex)
{
throw new JsonParseProxySettingException($"load file setting from {fileName} fail", ex);
}
catch (JsonReaderException ex)
{
throw new JsonParseProxySettinggParseException($"parse file setting from {fileName} fail", ex);
}
}
}
[Serializable]
public class JsonParseProxySettingException : Exception
{
public JsonParseProxySettingException(string message) : base(message)
{
}
public JsonParseProxySettingException(string message, Exception inner) : base(message, inner)
{
}
}
[Serializable]
public class JsonParseProxySettinggParseException : Exception
{
public JsonParseProxySettinggParseException(string message) : base(message)
{
}
public JsonParseProxySettinggParseException(string message, Exception inner) : base(message, inner)
{
}
}
}
Program.cs:
namespace JsonParseProxy
{
class Program
{
static void Main(string[] args)
{
try
{
var r = new JsonParseProxy($"{AppDomain.CurrentDomain.BaseDirectory}/Myfile.txt");
foreach (var item in r.Load<MyClass>())
{
Console.WriteLine(item.Name);
Console.WriteLine(item.Age);
Console.WriteLine("=============");
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
public class MyClass
{
public string Name { get; set; }
public string Age { get; set; }
}
}
上述程式碼我們多切了一層中介層,讓呼叫端相依JsonParseProxy.cs,當需要更換實作或套件時,只需要異動JsonParseProxy.cs,並且也制定了Domain Exception,則提供了更清楚 的例外辨識度,我們把IOException 及 JsonReaderException 封裝後拋出,因為呼叫者不需要得知你的內部行為。