C# 设计模式系列教程-外观模式

下面是基于 Markdown 格式的完整攻略:

C# 设计模式系列教程-外观模式

什么是外观模式

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个简单的界面,隐藏了复杂的系统,并且将系统中的多个组件打包成一个单一的组件,从而使得系统更加容易使用和更加易于维护。

外观模式解决了什么问题

在一个复杂的系统中,有时候我们不想暴露系统的所有细节给用户,因为这些细节可能会使得使用系统的用户非常困难。此时,我们可以使用外观模式,提供一个简单的界面,隐藏系统的所有细节,使得用户更容易使用系统。

外观模式的工作方式类似于酒店的前台接待员。我们去酒店住宿,只需要跟前台打招呼,然后告诉前台我们要住几天,前台会在后台帮我们完成所有的手续,然后把钥匙交给我们。我们不需要知道后面的所有手续和细节,只需要跟前台打招呼即可。

外观模式的角色

外观模式主要包含以下角色:

  • Facade(外观):对外提供简单的接口,对内部的复杂系统进行封装。
  • Subsystem(子系统):系统中的各个组件,由外观模式进行统一的封装。

外观模式的实现

下面通过一个简单的示例来讲解外观模式的实现。

示例一

我们现在要实现一个手机销售系统,这个系统可以销售多种品牌的手机,每种手机都有自己的价格和库存。我们需要实现一个外观模式,使得用户可以通过一个简单的接口来查询手机的价格和库存。

下面是具体的实现步骤。

  1. 定义一个手机类,包含手机品牌、价格和库存信息:
public class MobilePhone
{
    public string Brand { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
}
  1. 定义一个手机库存类,用于保存所有手机的信息:
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;
    }
}
  1. 定义一个手机外观类,用于封装手机的价格和库存信息:
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;
    }
}
  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}");

示例二

下面再通过一个更加复杂的示例来讲解外观模式的实现。

我们现在要实现一个视频编辑软件,这个软件可以导入多种格式的视频文件,可以编辑视频的时间线、添加特效、添加字幕等等。我们需要实现一个外观模式,使得用户可以通过一个简单的接口来导入视频、编辑视频等操作。

下面是具体的实现步骤。

  1. 定义一个视频类,包含视频的文件名和时长信息:
public class Video
{
    public string FileName { get; set; }
    public TimeSpan Duration { get; set; }
}
  1. 定义一个视频导入类,用于导入视频文件:
public class VideoImporter
{
    public Video ImportVideo(string fileName)
    {
        // 打开视频文件,读取时长等信息
        // ...
        var video = new Video { FileName = fileName, Duration = TimeSpan.FromSeconds(120) };
        return video;
    }
}
  1. 定义一个视频编辑类,用于编辑视频:
public class VideoEditor
{
    public void AddEffect(Video video, string effectName)
    {
        // 添加特效
        // ...
    }

    public void AddSubtitle(Video video, string subtitleText)
    {
        // 添加字幕
        // ...
    }

    // 更多编辑操作
    // ...

    public void SaveVideo(Video video, string fileName)
    {
        // 保存视频
        // ...
    }
}
  1. 定义一个视频外观类,用于封装视频的导入和编辑操作:
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);
    }
}
  1. 客户端代码使用视频外观类来导入视频、编辑视频等操作:
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");

外观模式的优缺点

优点

  1. 简化了系统的使用:外观模式提供了一个简单的接口,让用户不需要了解系统的内部结构和实现,从而让系统更容易使用。
  2. 隐藏了系统的复杂性:外观模式可以将系统的多个组件打包成一个单一的组件,隐藏了系统的复杂性,从而让系统更容易维护和升级。
  3. 解耦了系统和客户端:客户端只需要与外观接口进行交互,不需要了解内部的实现细节,从而解耦了系统和客户端之间的依赖关系。

缺点

  1. 系统的灵活性降低:外观模式封装了系统的多个组件,可能会导致系统的灵活性降低。
  2. 不符合开闭原则:如果要改变系统的内部实现,可能需要改变外观类的代码,不符合开闭原则。

总结

外观模式是一种非常常用的设计模式,它可以将复杂的系统封装成一个简单的接口,让用户不需要了解系统的内部结构和实现,从而让系统更容易使用和更加易于维护。使用外观模式需要注意灵活性和开闭原则的问题,需要谨慎设计。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 设计模式系列教程-外观模式 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • C#基础:Dispose()、Close()、Finalize()的区别详解

    标题:C#基础:Dispose()、Close()、Finalize()的区别详解 介绍:在C#中,Dispose()、Close()、Finalize()都是释放资源的方式,但是它们之间有着不同的使用场景和语义。本文将对这三者进行详细介绍,并给出使用示例。 正文:一、Dispose()Dispose()是一种显式释放资源的方法,它是IDisposable接…

    C# 2023年5月15日
    00
  • C# WinForm国际化实现的简单方法

    那么下面我来详细讲解一下“C# WinForm国际化实现的简单方法”。 什么是国际化 国际化(Internationalization),简称I18N,指将软件(尤其是在开发过程中)设计成可同时支持多种语言和字符集的技术。通俗点说,国际化就是将我们的程序在不同地区、不同语言下也能够顺利运行,显示相应的语言文本和界面信息。 WinForm国际化实现的简单方法 …

    C# 2023年6月6日
    00
  • C#检查foreach判读是否为null的方法

    当我们使用foreach循环访问集合或数组时,必须确保集合或数组不为null,否则会抛出NullReferenceException异常。在C#中,有多种方式可以检查集合或数组是否为null,本篇攻略将带你了解其中的两种方法。 方法1:使用if判断 我们可以使用if条件语句来判断集合或数组是否为null。在使用foreach循环之前,先检查集合或数组是否为n…

    C# 2023年5月15日
    00
  • 详解C#中的泛型以及编程中使用泛型的优点

    我非常乐意讲解一下C#中的泛型以及如何通过泛型编程来提高代码的重用性和可维护性。 什么是泛型 泛型是一种可以实现类型参数化的编程方法。在编写程序时,我们通常会创建不同类型的数据结构和函数。在C#中,这些数据结构和函数的类型通常会由具体的类型来决定。而泛型则提供了一种方法来针对具有相同结构的不同类型,提高我们代码的重用性。 举个例子,你可以声明一个泛型类,这个…

    C# 2023年6月3日
    00
  • 浅谈JsonObject中的key-value数据解析排序问题

    浅谈JsonObject中的key-value数据解析排序问题——攻略 问题描述 在使用JsonObject进行key-value数据解析时,有时我们会发现得到的数据不是按照期望的顺序排列的。这个问题会给我们的主观体验带来很大不便,并且也可能对我们的后续工作造成困扰。所以在这篇文章中,我们将会讨论这个问题的产生原因以及解决方案。 问题产生的原因 当我们使用J…

    C# 2023年6月1日
    00
  • DataGridView控件显示行号的正确代码及分析

    DataGridView控件显示行号的正确代码及分析 DataGridView控件是Windows Form应用程序中最常用的数据显示控件之一。由于在处理大量数据时,通常需要知道每一行数据的编号,因此给DataGridView控件加上行号是很有必要的。下面是实现DataGridView控件显示行号的正确代码及分析。 步骤一:添加行号列 首先,我们需要为Dat…

    C# 2023年5月15日
    00
  • ASP.NET MVC实现城市或车型三级联动

    当我们需要实现城市或车型三级联动的功能时,可以使用 ASP.NET MVC 框架来实现。下面是详细的攻略: 步骤1:创建数据库 在 SQL Server 中创建一个名为“City”的数据库,并添加以下表: Province 表 列名 数据类型 Id int Name nvarchar(50) City 表 列名 数据类型 Id int Name nvarch…

    C# 2023年5月12日
    00
  • 怪物猎人世界狩猎笛怎么玩 新手演奏技巧及攻击系统介绍

    怪物猎人世界狩猎笛攻略 狩猎笛介绍 狩猎笛是怪物猎人世界中的一种武器,其特点在于可以演奏各种旋律,对自身和队友产生不同的效果。 和其他武器相比,狩猎笛玩家需要注意的是不仅仅要打出伤害,还需要根据不同的战斗情况演奏出合适的旋律以增强自身和队友的能力。 狩猎笛攻略 熟悉狩猎笛攻击模式 狩猎笛有两种攻击模式,即打击模式和演奏模式。打击模式下可以使用基础的攻击招式,…

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部