PatternsCSharpExtraAddons/Patterns/Pattern_2-Шаблонный метод/Program.cs
Dvurechensky a4cd4b4ced 1.0
Main
2024-10-05 09:30:14 +03:00

227 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* ПАТТЕРНЫ ПОВЕДЕНИЯ
*
* Глава_2 и 10: Фабричный метод(виртуальный конструктор) и Шаблонный метод (Паттерн поведения)
*
* — это каркас, в который наследники могут
* подставить реализации недостающих элементов.
*
* - позволяет более четко определить «контракт» между базовым классом и потомками
*/
using Behavioral;
using Creational;
using System.ServiceModel;
using System.Text;
/*
* Теперь все реализации читателей логов будут вынуждены следовать согласованному протоколу
*/
public abstract class LogReader
{
private int _currentPosition;
/// <summary>
/// Определяет алгоритм импорта
/// </summary>
/// <returns></returns>
public IEnumerable<LogEntry> ReadLogEntry()
{
return ReadEntries(ref _currentPosition).Select(ParseLogEntry);
}
protected abstract IEnumerable<string> ReadEntries(ref int position);
protected abstract LogEntry ParseLogEntry(string stringEntry);
}
/*
* 2.1: Локальный шаблонный метод на основе делегатов
*
* ! является более контекстно зависимой операцией
*
* Использование наследования является слишком тяжеловесным решением,
* поэтому в таких случаях применяется подход, при котором переменный шаг алгоритма задается делегатом
*/
/// <summary>
/// Поведение сервиса сохранения записей
/// </summary>
interface ILogSaver
{
void UploadLogEntries(IEnumerable<LogEntry>logEntries);
void UploadExceptions(IEnumerable<ExceptionLogEntry> exceptions);
}
/// <summary>
/// Прокси - класс инкапсулирует особенности работы
/// с WCF - инфраструктурой
/// </summary>
class LogSaverProxy : ILogSaver
{
/// <summary>
/// Подключение к службе
/// </summary>
class LogSaverClient : ClientBase<ILogSaver>
{
public ILogSaver LogSaver
{
get { return Channel; }
}
}
public void UploadExceptions(IEnumerable<ExceptionLogEntry> exceptions)
{
UseProxyClient(c => c.UploadExceptions(exceptions));
}
public void UploadLogEntries(IEnumerable<LogEntry> logEntries)
{
UseProxyClient(c => c.UploadLogEntries(logEntries));
}
private void UseProxyClient(Action<ILogSaver> accessor)
{
var client = new LogSaverClient();
try
{
accessor(client.LogSaver);
client.Close();
}
catch (CommunicationException e)
{
client.Abort();
Console.WriteLine(e.Message);
}
}
}
/*
* Подход на основе делегатов может не только применяться для определения
* локальных действий внутри класса, но и передаваться извне другому объекту
* в аргументах конструктора.
*/
/*
* 2.2: Шаблонный метод на основе методов расширения
*/
public abstract class LogEntryBase
{
public DateTime EntryDateTime { get; internal set; }
public LogType Severity { get; internal set; }
public string? Message { get; internal set; }
/// <summary>
/// ExceptionLogEntry - будет возвращать информацию об исключении
/// </summary>
public string? AdditionalInformation { get; internal set; }
}
public static class LogEntryBaseEx
{
public static string GetText(this LogEntryBase logEntry)
{
var sb = new StringBuilder();
sb.AppendFormat("{0}", logEntry.EntryDateTime)
.AppendFormat("{0}", logEntry.Severity)
.AppendLine(logEntry.Message)
.AppendLine(logEntry.AdditionalInformation);
return sb.ToString();
}
}
/// <summary>
/// Абстракция для взаимодействия с фабриками
/// </summary>
public abstract class Creator
{
private Product? product;
public abstract Product ProductFactoryMethod(int x, int y);
public abstract Product ProductFactoryMethod_2(int x, int y);
public void AnProductOperation(int x, int y)
{
product = ProductFactoryMethod(x, y);
}
public void AnProductOperation_2(int x, int y)
{
product = ProductFactoryMethod_2(x, y);
}
}
/// <summary>
/// Конкретная фабрика
/// </summary>
public class ConcreteCreator : Creator
{
public override Product ProductFactoryMethod(int x, int y)
{
return new ConcreteProduct(x, y);
}
public override Product ProductFactoryMethod_2(int x, int y)
{
return new ConcreteProduct_2(x, y);
}
}
/// <summary>
/// Абстракция для взаимодействия с продуктами
/// </summary>
public abstract class Product
{
public abstract void GetText();
}
/// <summary>
/// Конкретный продукт
/// </summary>
public class ConcreteProduct : Product
{
public ConcreteProduct(int x, int y)
{
Console.WriteLine($"x {x} y {y}");
}
public override void GetText()
{
Console.WriteLine("1");
}
}
public class ConcreteProduct_2 : Product
{
public ConcreteProduct_2(int x, int y)
{
Console.WriteLine($"x2 {x} y2 {y}");
}
public override void GetText()
{
Console.WriteLine("2");
}
}
public class Program
{
public static void Main(string[] args)
{
Product product1 = null;
Product product2 = null;
var creator = new ConcreteCreator(); //Инициализирую фабрику
product1 = creator.ProductFactoryMethod(1, 2);
product2 = creator.ProductFactoryMethod_2(1, 2);
Console.WriteLine($"{product1.GetType().Name} {product2.GetType().Name}");
product1.GetText();
product2.GetText();
}
}