下面是基于 Markdown 格式的完整攻略:
C# 设计模式系列教程-外观模式
什么是外观模式
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的界面,隐藏了复杂的系统,并且将系统中的多个组件打包成一个单一的组件,从而使得系统更加容易使用和更加易于维护。
外观模式解决了什么问题
在一个复杂的系统中,有时候我们不想暴露系统的所有细节给用户,因为这些细节可能会使得使用系统的用户非常困难。此时,我们可以使用外观模式,提供一个简单的界面,隐藏系统的所有细节,使得用户更容易使用系统。
外观模式的工作方式类似于酒店的前台接待员。我们去酒店住宿,只需要跟前台打招呼,然后告诉前台我们要住几天,前台会在后台帮我们完成所有的手续,然后把钥匙交给我们。我们不需要知道后面的所有手续和细节,只需要跟前台打招呼即可。
外观模式的角色
外观模式主要包含以下角色:
- Facade(外观):对外提供简单的接口,对内部的复杂系统进行封装。
- Subsystem(子系统):系统中的各个组件,由外观模式进行统一的封装。
外观模式的实现
下面通过一个简单的示例来讲解外观模式的实现。
示例一
我们现在要实现一个手机销售系统,这个系统可以销售多种品牌的手机,每种手机都有自己的价格和库存。我们需要实现一个外观模式,使得用户可以通过一个简单的接口来查询手机的价格和库存。
下面是具体的实现步骤。
- 定义一个手机类,包含手机品牌、价格和库存信息:
public class MobilePhone
{
public string Brand { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
}
- 定义一个手机库存类,用于保存所有手机的信息:
public class MobilePhoneStock
{
private Dictionary<string, MobilePhone> _stock = new Dictionary<string, MobilePhone>();
public MobilePhoneStock()
{
_stock.Add("Apple iPhone X", new MobilePhone { Brand = "Apple", Price = 8999, Stock = 100 });
_stock.Add("Samsung Galaxy S10", new MobilePhone { Brand = "Samsung", Price = 7999, Stock = 200 });
_stock.Add("Huawei P30 Pro", new MobilePhone { Brand = "Huawei", Price = 6999, Stock = 300 });
}
public MobilePhone GetMobilePhone(string name)
{
if (_stock.ContainsKey(name))
{
return _stock[name];
}
return null;
}
}
- 定义一个手机外观类,用于封装手机的价格和库存信息:
public class MobilePhoneFacade
{
private readonly MobilePhoneStock _stock = new MobilePhoneStock();
public decimal GetMobilePhonePrice(string name)
{
var mobile = _stock.GetMobilePhone(name);
if (mobile != null)
{
return mobile.Price;
}
return -1;
}
public int GetMobilePhoneStock(string name)
{
var mobile = _stock.GetMobilePhone(name);
if (mobile != null)
{
return mobile.Stock;
}
return -1;
}
}
- 客户端代码使用手机外观类来查询手机信息:
var facade = new MobilePhoneFacade();
var price1 = facade.GetMobilePhonePrice("Apple iPhone X");
var price2 = facade.GetMobilePhonePrice("Samsung Galaxy S10");
var price3 = facade.GetMobilePhonePrice("Huawei P30 Pro");
var price4 = facade.GetMobilePhonePrice("Xiaomi Mi 9");
Console.WriteLine($"Price of Apple iPhone X: {price1}");
Console.WriteLine($"Price of Samsung Galaxy S10: {price2}");
Console.WriteLine($"Price of Huawei P30 Pro: {price3}");
Console.WriteLine($"Price of Xiaomi Mi 9: {price4}");
var stock1 = facade.GetMobilePhoneStock("Apple iPhone X");
var stock2 = facade.GetMobilePhoneStock("Samsung Galaxy S10");
var stock3 = facade.GetMobilePhoneStock("Huawei P30 Pro");
var stock4 = facade.GetMobilePhoneStock("Xiaomi Mi 9");
Console.WriteLine($"Stock of Apple iPhone X: {stock1}");
Console.WriteLine($"Stock of Samsung Galaxy S10: {stock2}");
Console.WriteLine($"Stock of Huawei P30 Pro: {stock3}");
Console.WriteLine($"Stock of Xiaomi Mi 9: {stock4}");
示例二
下面再通过一个更加复杂的示例来讲解外观模式的实现。
我们现在要实现一个视频编辑软件,这个软件可以导入多种格式的视频文件,可以编辑视频的时间线、添加特效、添加字幕等等。我们需要实现一个外观模式,使得用户可以通过一个简单的接口来导入视频、编辑视频等操作。
下面是具体的实现步骤。
- 定义一个视频类,包含视频的文件名和时长信息:
public class Video
{
public string FileName { get; set; }
public TimeSpan Duration { get; set; }
}
- 定义一个视频导入类,用于导入视频文件:
public class VideoImporter
{
public Video ImportVideo(string fileName)
{
// 打开视频文件,读取时长等信息
// ...
var video = new Video { FileName = fileName, Duration = TimeSpan.FromSeconds(120) };
return video;
}
}
- 定义一个视频编辑类,用于编辑视频:
public class VideoEditor
{
public void AddEffect(Video video, string effectName)
{
// 添加特效
// ...
}
public void AddSubtitle(Video video, string subtitleText)
{
// 添加字幕
// ...
}
// 更多编辑操作
// ...
public void SaveVideo(Video video, string fileName)
{
// 保存视频
// ...
}
}
- 定义一个视频外观类,用于封装视频的导入和编辑操作:
public class VideoFacade
{
private readonly VideoImporter _importer = new VideoImporter();
private readonly VideoEditor _editor = new VideoEditor();
public Video ImportVideo(string fileName)
{
return _importer.ImportVideo(fileName);
}
public void AddEffect(Video video, string effectName)
{
_editor.AddEffect(video, effectName);
}
public void AddSubtitle(Video video, string subtitleText)
{
_editor.AddSubtitle(video, subtitleText);
}
public void SaveVideo(Video video, string fileName)
{
_editor.SaveVideo(video, fileName);
}
}
- 客户端代码使用视频外观类来导入视频、编辑视频等操作:
var facade = new VideoFacade();
var video = facade.ImportVideo("test.mp4");
facade.AddEffect(video, "slow motion");
facade.AddSubtitle(video, "hello world");
facade.SaveVideo(video, "output.mp4");
外观模式的优缺点
优点
- 简化了系统的使用:外观模式提供了一个简单的接口,让用户不需要了解系统的内部结构和实现,从而让系统更容易使用。
- 隐藏了系统的复杂性:外观模式可以将系统的多个组件打包成一个单一的组件,隐藏了系统的复杂性,从而让系统更容易维护和升级。
- 解耦了系统和客户端:客户端只需要与外观接口进行交互,不需要了解内部的实现细节,从而解耦了系统和客户端之间的依赖关系。
缺点
- 系统的灵活性降低:外观模式封装了系统的多个组件,可能会导致系统的灵活性降低。
- 不符合开闭原则:如果要改变系统的内部实现,可能需要改变外观类的代码,不符合开闭原则。
总结
外观模式是一种非常常用的设计模式,它可以将复杂的系统封装成一个简单的接口,让用户不需要了解系统的内部结构和实现,从而让系统更容易使用和更加易于维护。使用外观模式需要注意灵活性和开闭原则的问题,需要谨慎设计。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 设计模式系列教程-外观模式 - Python技术站