Composite.cs
Код подключён напрямую из исходного файла в кодировке UTF-8, поэтому эта страница всегда показывает его актуальную версию.
← К конспекту
Скачать исходный файл
| Composite.cs |
|---|
| using System;
using System.Collections.Generic;
using System.Linq;
namespace DesignPatterns.Structural.Composite
{
// Общий интерфейс и для листьев (файлов), и для составных узлов (папок) -
// клиент работает с деревом единообразно, не различая типы узлов.
public interface IFileSystemEntry
{
string Name { get; }
long GetSize();
void Print(int indent = 0);
}
// Лист - не имеет дочерних элементов
public sealed class FileEntry : IFileSystemEntry
{
public string Name { get; }
private readonly long _size;
public FileEntry(string name, long size)
{
Name = name;
_size = size;
}
public long GetSize() => _size;
public void Print(int indent = 0) =>
Console.WriteLine(new string(' ', indent) + $"- {Name} ({_size} байт)");
}
// Составной узел - хранит коллекцию дочерних элементов,
// которые сами могут быть либо листьями, либо другими составными узлами.
public sealed class FolderEntry : IFileSystemEntry
{
public string Name { get; }
private readonly List<IFileSystemEntry> _children = new();
public FolderEntry(string name)
{
Name = name;
}
public void Add(IFileSystemEntry entry) => _children.Add(entry);
// Размер папки - рекурсивная сумма размеров всех дочерних элементов.
// Вызывающему коду не важно, лист это или снова папка.
public long GetSize() => _children.Sum(c => c.GetSize());
public void Print(int indent = 0)
{
Console.WriteLine(new string(' ', indent) + $"+ {Name}/ ({GetSize()} байт)");
foreach (var child in _children)
{
child.Print(indent + 2);
}
}
}
public static class Demo
{
public static void Run()
{
var root = new FolderEntry("project");
var src = new FolderEntry("src");
src.Add(new FileEntry("Program.cs", 1200));
src.Add(new FileEntry("Utils.cs", 800));
var docs = new FolderEntry("docs");
docs.Add(new FileEntry("README.md", 500));
root.Add(src);
root.Add(docs);
root.Add(new FileEntry(".gitignore", 50));
// Клиент вызывает Print/GetSize на корне, не зная заранее,
// сколько уровней вложенности внутри.
root.Print();
}
}
}
|