Архив рубрики ‘Паттерны’

Шаблон Strategy

Пару слов: смысл в том, чтобы иметь переменную типа «алгоритм», а не использовать тяжелое наследование.

Шаблон Decorator

Пару слов: для избежания изменения базовых классов они оборачиваются в декоратор с добавлением функциональности. Можно несколько декораторов наследовать от декорируемого класса, и оборачивать их друг в друга.

Шаблон Factory

Пару слов: чтобы не писать много условий создания объектов в разных местах, их сначала выносят в отдельный метод. При дальнейшем развитии эти методы можно объединить в отдельном классе «фабрике». При дальнейшем развитии создаются «фабрики» на каждое условие, и выделяется «абстрактная фабрика» создающая «конкретные фабрики».

Шаблон Observer

Пару слов: объект хранит в себе список «наблюдателей». При наступлении определенного события он извещает всех «наблюдателей».

Шаблон Chain of Responsibility

Пару слов: объект хранит в себе только следующий ответственный объект. При наступлении определенного события и невозможности его обработать он извещает только следующий ответственный объект.

Шаблон Flyweight

Пару слов: можно хранить не список тяжеловесных объектов, а список легковесных настроект и несколько тяжеловесных объектов. Один и тот же объект, в зависимости от настроек, может действовать несколько разных объектов.

Шаблон Adapter

Пару слов: объект, реализующий нужных интерфейс, хранит в себе объект, реализующий ненужный интерфейс, и преобразует его интерфейс в свой.

Шаблон Facade

Пару слов: прячет большой уродливый API за маленьким красивым.

Шаблон Template Design

Пару слов: «шаблонный метод», который нельзя переопределить в потомках, но необходимо переопределить методы, вызываемые в определенном порядке из «шаблонного».

Шаблон Builder

Пару слов: «строитель» может «делать» определенный объект по частям. Хорошая реализация, когда builder object передает список действий buildable object, который в свою очередь возвращает нужных объект, последовательно выполняя список действий.

Шаблон Composite

Пару слов: шаблон хорош для обхода деревьев, где узлы трактуются также как листья.

Шаблон Visitor
Пару слов: в отличие от composite, при обходе дерева, всем элементам нужно передавать объект visitor, который сам знает что делать с узлами и листьями. По сути идет передача алгоритма обработки.

Шаблон State

Пару слов: все конечные автоматы построены на этой идее. А конечные автоматы идеальны при разборе текста.

Шаблон Proxy

Пару слов: локальный представитель удаленного объекта или сервиса.

Шаблон Command

Пару слов: объектная оболочка для действия. Очень хорош в текстовых редакторах для Undo/Redo.

Шаблон Mediator

Пару слов: чтобы объекты не общались друг с другом напрямую, все их запросы идут в объект «посредник», который затем решает кому их передать.

Шаблон Prototype

Пару слов: а-ля clone().

Шаблон Memento
Пару слов: хранит в себе начальное состояние объекта.

Шаблон Interpreter
Пару слов: только для реализации своего языка.

Реклама

Паттерн Memento

Posted: Апрель 21, 2011 in .NET, Паттерны
public class Memento<T>
{
	private Dictionary<PropertyInfo, object> storedProperties = new Dictionary<PropertyInfo, object>();

	public Memento( T originator )
	{
		this.InitializeMemento( originator );
	}

	public T Originator
	{
		get;
		protected set;
	}

	public void Restore( T originator )
	{
		foreach ( var pair in this.storedProperties )
		{
			pair.Key.SetValue( originator, pair.Value, null );
		}
	}

	private void InitializeMemento( T originator )
	{
		if ( originator == null )
			throw new ArgumentNullException( "Originator", "Originator cannot be null" );

		this.Originator = originator;
		IEnumerable<PropertyInfo> propertyInfos = typeof( T ).GetProperties( BindingFlags.Public | BindingFlags.Instance ).Where( p => p.CanRead && p.CanWrite );

		foreach ( PropertyInfo property in propertyInfos )
			this.storedProperties[ property ] = property.GetValue( originator, null );
	}
}

Шаблон Specification

Posted: Январь 4, 2011 in .NET, Паттерны

Фреймворк:

    public interface ISpecification<T>
        where T : class
    {
        ISpecification<T> And(ISpecification<T> spec);
        ISpecification<T> Or(ISpecification<T> spec);
        ISpecification<T> Not(ISpecification<T> spec);
        bool IsSatisfiedBy(T candidate);
    }

    public abstract class Specification<T> : ISpecification<T>
        where T : class
    {
        public ISpecification<T> And(ISpecification<T> spec)
        {
            return new AndSpecification<T>(this, spec);
        }

        public ISpecification<T> Or(ISpecification<T> spec)
        {
            return new OrSpecification<T>(this, spec);
        }

        public ISpecification<T> Not(ISpecification<T> spec)
        {
            return new NotSpecification<T>(this);
        }

        public abstract bool IsSatisfiedBy(T candidate);
    }

    public abstract class CompositeSpecification<T> : Specification<T>
        where T : class
    {
        protected readonly Specification<T> left;
        protected readonly ISpecification<T> right;

        public CompositeSpecification(Specification<T> left, ISpecification<T> right)
        {
            this.left = left;
            this.right = right;
        }
    }

    public class AndSpecification<T> : CompositeSpecification<T>
        where T : class
    {
        public AndSpecification(Specification<T> left, ISpecification<T> right)
            : base(left, right)
        {
        }

        public override bool IsSatisfiedBy(T candidate)
        {
            return left.IsSatisfiedBy(candidate) && right.IsSatisfiedBy(candidate);
        }
    }

    public class NotSpecification<T> : Specification<T>
        where T : class
    {
        private readonly Specification<T> specification;

        public NotSpecification(Specification<T> specification)
        {
            this.specification = specification;
        }
        public override bool IsSatisfiedBy(T candidate)
        {
            return !specification.IsSatisfiedBy(candidate);
        }
    }

    public class OrSpecification<T> : CompositeSpecification<T>
        where T : class
    {
        public OrSpecification(Specification<T> left, ISpecification<T> right)
            : base(left, right)
        {

        }
        public override bool IsSatisfiedBy(T candidate)
        {
            return left.IsSatisfiedBy(candidate) || right.IsSatisfiedBy(candidate);
        }
    }

Конкретные спецификации:

 public class DbUniqueSteamIdSpecification : Specification<Claim>
    {
        public override bool IsSatisfiedBy(Claim candidate)
        {
           return !ValidationService.HasParticipantPropertyValueInDB("SteamID", candidate.SteamID);
        }
    }

 public class DbUniqueIcqSpecification : Specification<Claim>
    {
        public override bool IsSatisfiedBy(Claim candidate)
        {
            return !ValidationService.HasParticipantPropertyValueInDB("ICQ", candidate.ICQ);
        }
    }

 public class DbUniqueClaimSpecification : Specification<Claim>
    {
        readonly DbUniqueIcqSpecification icq = new DbUniqueIcqSpecification();
        readonly DbUniqueSteamIdSpecification steamID = new DbUniqueSteamIdSpecification();

        public override bool IsSatisfiedBy(Claim candidate)
        {
            return icq
                 .And(steamID)
                 .IsSatisfiedBy(candidate);
        }
    }

Strategy-паттерн

Posted: Январь 4, 2011 in .NET, Паттерны
    #region Strategies
    public enum LoggingStrategy
    {
        Console,
        Trace
    }
    #endregion

    #region Service
    public class LoggingService
    {
        private readonly Dictionary<LoggingStrategy, ILogger> _strategies = new Dictionary<LoggingStrategy, ILogger>();

        public LoggingService()
        {
            DefineStrategies();
        }

        public void LogMessage(LoggingStrategy strategy, string message)
        {
            _strategies[strategy].LogMessage(message);
        }

        public void LogError(LoggingStrategy strategy, string errorMessage)
        {
            _strategies[strategy].LogMessage(errorMessage);
        }

        private void DefineStrategies()
        {
            _strategies.Add(LoggingStrategy.Console, new ConsoleLogger());
            _strategies.Add(LoggingStrategy.Trace, new TraceLogger());
        }
    }
    #endregion

    #region Loggers
    public interface ILogger
    {
        void LogMessage(string message);
        void LogError(string errorMessage);
    }

    public class ConsoleLogger : ILogger
    {
        public void LogMessage(string message)
        {
            System.Console.WriteLine(String.Format("Message: {0}", message));
        }
        public void LogError(string errorMessage)
        {
            System.Console.WriteLine(String.Format("Error: {0}", errorMessage));
        }
    }

    public class TraceLogger : ILogger
    {
        public void LogMessage(string message)
        {
            System.Diagnostics.Trace.WriteLine(String.Format("Message: {0}", message));
        }
        public void LogError(string errorMessage)
        {
            System.Diagnostics.Trace.WriteLine(String.Format("Error: {0}", errorMessage));
        }
    }