C#中的composite模式示例详解

C#中的Composite模式示例详解

Composite模式是一种结构型设计模式,它可以通过组合多个对象来创建一个复杂的结构,并且与它们的父对象一起使用。这种模式可以让客户端代码以统一的方式来处理单个对象和对象组合的结构,而不需要区分它们之间的差异,从而提高了代码的可维护性和可扩展性。接下来,我们将通过两个示例来详细讲解C#中的Composite模式。

示例一:图形绘制

假设我们要编写一个图形绘制程序,能够绘制基本的图形(如圆形、矩形、三角形等)以及复杂的组合图形(如多个基本图形组成的图形)。在这种情况下,我们可以使用Composite模式来实现。具体实现步骤如下:

步骤一:定义图形接口

我们首先需要定义一个表示图形的接口IShape,它包含了绘制图形的方法Draw()和计算面积的方法GetArea()

public interface IShape
{
    void Draw();
    double GetArea();
}

步骤二:实现基本图形类

我们实现三个基本图形类:圆形、矩形和三角形,它们都实现了IShape接口。

public class Circle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Draw Circle");
    }

    public double GetArea()
    {
        return Math.PI * r * r;
    }

    private double r;
}

public class Rectangle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Draw Rectangle");
    }

    public double GetArea()
    {
        return w * h;
    }

    private double w;
    private double h;
}

public class Triangle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Draw Triangle");
    }

    public double GetArea()
    {
        return 0.5 * b * h;
    }

    private double b;
    private double h;
}

步骤三:实现图形组合类

我们定义一个表示图形组合的类CompositeShape,它包含了一个IShape类型的列表,在Draw()方法中遍历每个图形的绘制操作,在GetArea()方法中遍历每个图形的面积计算操作并累加结果。

public class CompositeShape : IShape
{
    public CompositeShape(ICollection<IShape> shapes)
    {
        this.shapes = shapes;
    }

    public void Draw()
    {
        foreach (var shape in shapes)
        {
            shape.Draw();
        }
    }

    public double GetArea()
    {
        double area = 0.0;
        foreach (var shape in shapes)
        {
            area += shape.GetArea();
        }
        return area;
    }

    private ICollection<IShape> shapes;
}

步骤四:使用图形绘制程序

我们可以通过如下代码来使用图形绘制程序:

var circle = new Circle();
var rectangle = new Rectangle();
var triangle = new Triangle();

var compositeShape = new CompositeShape(new IShape[] { circle, rectangle, triangle });
var area = compositeShape.GetArea();
Console.WriteLine($"The area of the composite shape is {area}");

示例二:文件系统管理

假设我们要实现一个文件系统管理程序,能够对文件和文件夹进行增、删、改、查等操作。在这种情况下,我们可以使用Composite模式来实现。具体实现步骤如下:

步骤一:定义文件系统接口

我们首先需要定义一个表示文件系统节点的接口IFileSystemNode,它包含了常用的增、删、改、查等方法。

public interface IFileSystemNode
{
    string Name { get; }
    bool IsDirectory { get; }
    void Add(IFileSystemNode node);
    void Remove(IFileSystemNode node);
    IFileSystemNode GetChildByName(string name);
}

步骤二:实现文件和文件夹类

我们实现两个类:文件和文件夹,它们都实现了IFileSystemNode接口。文件类只包含了文件名,而文件夹类还包含了一个子文件系统节点列表。

public class File : IFileSystemNode
{
    public File(string name)
    {
        this.name = name;
    }

    public string Name
    {
        get { return name; }
    }

    public bool IsDirectory
    {
        get { return false; }
    }

    public void Add(IFileSystemNode node)
    {
        throw new InvalidOperationException("Cannot add child node to file.");
    }

    public void Remove(IFileSystemNode node)
    {
        throw new InvalidOperationException("Cannot remove child node from file.");
    }

    public IFileSystemNode GetChildByName(string name)
    {
        throw new InvalidOperationException("Cannot get child node of file.");
    }

    private string name;
}

public class Directory : IFileSystemNode
{
    public Directory(string name)
    {
        this.name = name;
        this.children = new List<IFileSystemNode>();
    }

    public string Name
    {
        get { return name; }
    }

    public bool IsDirectory
    {
        get { return true; }
    }

    public void Add(IFileSystemNode node)
    {
        children.Add(node);
    }

    public void Remove(IFileSystemNode node)
    {
        children.Remove(node);
    }

    public IFileSystemNode GetChildByName(string name)
    {
        return children.FirstOrDefault(c => c.Name == name);
    }

    private string name;
    private List<IFileSystemNode> children;
}

步骤三:实现文件系统管理器

我们定义一个表示文件系统管理器的类FileSystemManager,它包含了一个根节点以及常用的增、删、改、查等方法,还包含了一个深度优先遍历方法Traverse(),可以遍历整个文件系统。

public class FileSystemManager
{
    public FileSystemManager()
    {
        root = new Directory("Root");
    }

    public void Add(IFileSystemNode node, string path)
    {
        var parent = GetParentNode(path);
        if (!parent.IsDirectory)
        {
            throw new InvalidOperationException("Cannot add child node to file.");
        }
        parent.Add(node);
    }

    public void Remove(string path)
    {
        var (parent, name) = GetParentNodeAndName(path);
        if (!parent.IsDirectory)
        {
            throw new InvalidOperationException("Cannot remove child node from file.");
        }
        var child = parent.GetChildByName(name);
        if (child == null)
        {
            throw new InvalidOperationException("Node not found.");
        }
        parent.Remove(child);
    }

    public void Rename(string path, string newName)
    {
        var (parent, name) = GetParentNodeAndName(path);
        if (!parent.IsDirectory)
        {
            throw new InvalidOperationException("Cannot rename file.");
        }
        var child = parent.GetChildByName(name);
        if (child == null)
        {
            throw new InvalidOperationException("Node not found.");
        }
        parent.Remove(child);
        child = child.IsDirectory
            ? new Directory(newName)
            : new File(newName);
        parent.Add(child, path.Substring(0, path.Length - name.Length) + newName);
    }

    public IFileSystemNode GetNode(string path)
    {
        var (parent, name) = GetParentNodeAndName(path);
        if (parent.IsDirectory)
        {
            return parent.GetChildByName(name);
        }
        else if (parent != null && parent.Name == name)
        {
            return parent;
        }
        else
        {
            throw new InvalidOperationException("Node not found.");
        }
    }

    public void Traverse(Action<IFileSystemNode> action)
    {
        Traverse(root, action);
    }

    private void Traverse(IFileSystemNode node, Action<IFileSystemNode> action)
    {
        action(node);
        if (node.IsDirectory)
        {
            foreach (var child in (node as Directory).GetChildren())
            {
                Traverse(child, action);
            }
        }
    }

    private IFileSystemNode GetParentNode(string path)
    {
        var parts = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length == 1 && parts[0] == root.Name)
        {
            return root;
        }
        var parent = root.GetChildByName(parts[0]);
        if (parent == null)
        {
            throw new InvalidOperationException("Invalid path.");
        }
        for (int i = 1; i < parts.Length - 1; i++)
        {
            var child = parent.GetChildByName(parts[i]);
            if (child == null || !child.IsDirectory)
            {
                throw new InvalidOperationException("Invalid path.");
            }
            parent = child;
        }
        return parent;
    }

    private (IFileSystemNode, string) GetParentNodeAndName(string path)
    {
        var parts = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length == 1 && parts[0] == root.Name)
        {
            return (null, "");
        }
        var parent = root.GetChildByName(parts[0]);
        if (parent == null)
        {
            throw new InvalidOperationException("Invalid path.");
        }
        for (int i = 1; i < parts.Length - 1; i++)
        {
            var child = parent.GetChildByName(parts[i]);
            if (child == null || !child.IsDirectory)
            {
                throw new InvalidOperationException("Invalid path.");
            }
            parent = child;
        }
        return (parent, parts[parts.Length - 1]);
    }

    private IFileSystemNode root;
}

步骤四:使用文件系统管理器

我们可以通过如下代码来使用文件系统管理器:

var manager = new FileSystemManager();

var rootDir = manager.GetNode("/Root");
var docsDir = new Directory("Documents");
manager.Add(docsDir, "/Root");
var readmeFile = new File("README.md");
manager.Add(readmeFile, "/Root/Documents/");
var todoFile = new File("TODO.md");
manager.Add(todoFile, "/Root/Documents/");
manager.Rename("/Root/Documents/TODO.md", "TASK.md");

manager.Traverse(node =>
{
    Console.WriteLine($"{(node.IsDirectory ? "Directory" : "File")} {node.Name}");
});

以上就是两个C#中实现Composite模式的示例,希望能对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#中的composite模式示例详解 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • 关于dotnet 替换 ASP.NET Core 的底层通讯为命名管道的 IPC 库的问题

    下面是关于“关于dotnet 替换 ASP.NET Core 的底层通讯为命名管道的 IPC 库的问题”的完整攻略,包含两个示例。 1. 什么是IPC IPC(Inter-Process Communication)是进程间通信的缩写。在计算机系统中,进程间通信是非常重要的,因为不同的进程需要共享数据和资源。IPC可以使不同的进程之间进行通信和协作,从而实现…

    C# 2023年5月15日
    00
  • asp.net webservice返回json的方法

    当我们使用ASP.NET Web Service时,返回JSON格式数据是常见的需求。下面是ASP.NET Web Service返回JSON格式数据的完整攻略: 步骤1:创建Web服务 首先,需要在ASP.NET项目中创建Web服务。可以在Visual Studio中选择“新建项目”->“ASP.NET Web应用程序”,然后选择“Web服务”模板进…

    C# 2023年5月31日
    00
  • PowerShell查看Windows功能选项的方法

    PowerShell查看Windows功能选项的方法 在PowerShell中,我们可以使用Get-WindowsOptionalFeature cmdlet命令来查看Windows功能选项。本文将提供详细的“PowerShell查看Windows功能选项的方法”的完整攻略,包括如何使用Get-WindowsOptionalFeature命令,以及两个示例。…

    C# 2023年5月15日
    00
  • C#面向对象实现图书管理系统

    C#面向对象实现图书管理系统 系统简介 图书管理系统是一个用于管理图书馆和书店的软件系统。该系统可以实现对图书的入库、出库、借阅、归还等操作,同时还可以对图书进行查询、统计、打印等功能的实现。本文介绍使用C#面向对象的编程思想实现图书管理系统的完整攻略。 系统设计 系统结构设计 我们可以将图书管理系统分为以下几个模块: 用户管理模块:用于管理系统用户的登录、…

    C# 2023年5月31日
    00
  • C#.net中的类型转换详细介绍

    请看下面的攻略。 C#.net中的类型转换详细介绍 基本概念 在C#.net中,类型转换是指将一种数据类型转换为另一种数据类型的过程。C#.net提供了多种类型转换的方式,例如隐式类型转换、显示类型转换、强制类型转换、装箱和拆箱等。需要注意的是,类型转换可能会造成数据精度的损失或者异常的产生。 隐式类型转换 当一个数据类型可以转换为另一个数据类型时,且转换不…

    C# 2023年5月14日
    00
  • C#的字符串比较

    C#中,字符串比较有多种方式,最常用的有三种:使用“==”比较,使用Equals方法比较,使用Compare方法比较。 使用“==”比较字符串 在C#中,可以使用“==”符号来比较两个字符串是否相等,例如: string str1 = "hello"; string str2 = "world"; string str…

    C# 2023年6月1日
    00
  • 在C#的类或结构中重写ToString方法的用法简介

    C#中的类和结构体都继承了Object类,而Object类中有一个ToString方法,用于将对象转换为字符串。但是,由于Object类中的ToString方法返回对象类型的名称,而不是对象本身的有用信息,因此我们可能希望在自己的类中重写ToString方法以提供更有用的文本表示。 以下是在C#中重写ToString方法的用法简介: 重写ToString方法…

    C# 2023年6月7日
    00
  • jQuery实现的AJAX简单弹出层效果代码

    jQuery是一种流行的JavaScript库,它提供了许多方便的方法来操作HTML文档、处理事件、执行动画等。其中,jQuery的AJAX功能可以让我们通过异步请求从服务器获取数据,而不必刷新整个页面。本文将提供详解“jQuery实现的AJAX简单弹出层效果代码”的完整攻略,包括如何使用jQuery的AJAX功能、如何使用jQuery实现弹出层效果等。 使…

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