Mikhail Valkov_Antipatterns

25
АНТИПАТЕРНЫ ПРОГРАММИРОВАНИЯ 2011 Part 1

description

 

Transcript of Mikhail Valkov_Antipatterns

Page 1: Mikhail Valkov_Antipatterns

АНТИПАТЕРНЫ ПРОГРАММИРОВАНИЯ2011

Part 1

Page 2: Mikhail Valkov_Antipatterns

• What is patterns ?• Patterns for patterns• Target patterns•  Structural patterns• Creational patterns• Optimization example

Page 3: Mikhail Valkov_Antipatterns

• Дубликаты кода• Большая вложенность внутри

метода• Магические константы• Суперклассы, интерфейсы,

методы• Public только для тестов

Page 4: Mikhail Valkov_Antipatterns

 Structural patterns

Proxy

Adapter

Facade

Bridge

Decorator

Composite

Page 5: Mikhail Valkov_Antipatterns

 Structural patternsProxyСлужит для управления доступом к заданному объекту, перехватывая вызовы к нему. Ни интерфейс ни функциональность замещенного компонента, для клиента, не должна изменяются.

Используется:• работа с объектом не должна зависеть от того, где он

реально расположен

Page 6: Mikhail Valkov_Antipatterns

 Structural patternsAdapterСлужит для приведения интерфейса объекта к требуемому виду.

• существующий объект, называемый адаптируемым, предоставляет необходимые функции, но не поддерживает нужного интерфейса;

• неизвестно заранее, с каким интерфейсами придется работать адаптируемому объекту;

Page 7: Mikhail Valkov_Antipatterns

 Structural patternsFacadeОбъединяет группу объектов в рамках одного специализированного интерфейса и переадресует вызовы его методов к этим объектам.

Используется:• упростить доступ к сложной системе;• создать различные уровни доступа к системе;

Page 8: Mikhail Valkov_Antipatterns

 Structural patternsBridgeПозволяет разделить объект на абстракцию и реализацию так, чтобы они могли изменяться независимо друг от друга.

Используется:• независимо изменять интерфейс работы с клиентом и

реализацию;• выбирать реализацию в процессе работы программы;

Page 9: Mikhail Valkov_Antipatterns

 Structural patternsDecoratorДекоратор предназначен для динамического добавления объекту новой функциональности. 

Используется:• динамически и прозрачно для клиента изменять

функциональность объекта;• реализовать небольшую функциональность, которая в

дальнейшем может быть исключена;

Page 10: Mikhail Valkov_Antipatterns

 Structural patternsCompositeПозволяет упростить и стандартизировать взаимодействие между клиентом и группой объектов, представляющих древовидную структуру или части составного объекта.Используется:• представить группу объектов в виде "составной объект –

его части";• для обращения как к составным объектам, так и к

отдельным частям.

Page 11: Mikhail Valkov_Antipatterns

Creational patterns

Singleton

Multiton

Object pool/Cache

Prototype

Builder

Page 12: Mikhail Valkov_Antipatterns

Creational patternsSingletonПредоставляет доступ к объекту

public sealed class Singleton { private static Singleton instance;

private Singleton() { }

public static Singleton Instance { get { return instance ?? (instance = new Singleton()); } }}

Page 13: Mikhail Valkov_Antipatterns

Creational patternsSingletonpublic class Singleton<T> where T : class{ private static readonly Lazy<T> instance = new Lazy<T>( () => (T)typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[0], null).Invoke(null));

public static T Instance { get {

return instance.Value; } }

}

Page 14: Mikhail Valkov_Antipatterns

Creational patternsMultitonСоздаёт определенное число своих экземпляров и предоставляет точку доступа для работы с ними. Каждый экземпляр связан с уникальным идентификатором.

public sealed class Multiton<TKey> { private static readonly ConcurrentDictionary<TKey, Multiton<TKey>> instances = new ConcurrentDictionary<TKey, Multiton<TKey>>();

private Multiton(TKey key) { /* ... */ }

public static Multiton<TKey> GetInstance(TKey key) { return instances.GetOrAdd(key, x => new Multiton<TKey>(x)); } }

Page 15: Mikhail Valkov_Antipatterns

Creational patternsObject poolПредназначен хранения готовых к использованию объектов. Когда системе требуется новый объект, он запрашивается из Пула, минуя процесс порождения. А после использования возвращается обратно в Пул вместо уничтожения.

Используется:• объекты часто создаются и уничтожаются;• создание/уничтожение объекта являются очень затратными

операциями.

Page 16: Mikhail Valkov_Antipatterns

Creational patternsObject pool/Cache

public interface IPoolObjectCreator<out T>{ T Create();}

public class DefaultObjectCreator<T> : IPoolObjectCreator<T> where T : class, new(){ T IPoolObjectCreator<T>.Create() { return new T(); }}

public class ObjectPool<T> where T : class, IPoolable{ private readonly ConcurrentBag<T> container = new ConcurrentBag<T>();}

Page 17: Mikhail Valkov_Antipatterns

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

реализации входящих в нее объектов;• класс порождаемого объекта определяется в момент

выполнения;public abstract class SimpleElement{ public uint Id { get; set; }

public string Title { get; set; }

public virtual SimpleElement Clone() { return (SimpleElement)this.MemberwiseClone(); }}

Page 18: Mikhail Valkov_Antipatterns

Creational patternsPrototypepublic abstract class SimpleElement{ public Guid Id { get; set; }

public string Title { get; set; }

public virtual SimpleElement Clone() { return (SimpleElement)this.MemberwiseClone(); }}

public void CopyObjects(IEnumerable<SimpleElement> selectedElements){

foreach (SimpleElement element in selectedElements) { SimpleElement newElement = element.Clone(); newElement.Id = Guid.NewGuid(); this.AddNewElement(newElement);

}}

Page 19: Mikhail Valkov_Antipatterns

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

Используется:• алгоритм этого процесса не должен зависеть от того, из

каких частей состоит объект;• конструирование должно обеспечивать возможность

создавать различные объекты.

Page 20: Mikhail Valkov_Antipatterns

Factory MethodПрименяется для создания объектов с определенным интерфейсом или абстрактным классом, реализации

которого предоставляются потомкам.

Abstract Factory

Factory

Factory Method

Page 21: Mikhail Valkov_Antipatterns

public interface IDataStorage { void Save(Stream stream);

  Stream Load(); } public abstract class DocumentManager{ public abstract IDataStorage CreateStorage();} public class FileStorageManager : DocumentManager { private class FileStorage : IDataStorage { /* … */ }  public override IDataStorage CreateStorage() { return new FileStorage(); } }

public class MemeoryStorageManager : DocumentManager { private class MemeoryStorage : IDataStorage { /* … */ } public override IDataStorage CreateStorage() { return new MemeoryStorage(); } } 

Factory MethodРЕАЛИЗАЦИЯ

Page 22: Mikhail Valkov_Antipatterns

public enum StorageFormat{ File,

Memory}

static void Main(string[] args){ IDataStorage storage = CreateStorage(StorageFormat.Memory); storage.Load();}

static IDataStorage CreateStorage(StorageFormat format){ switch (format) { case StorageFormat.Memory: return new FileStorageManager().CreateStorage(); case StorageFormat.File: return new MemeoryStorageManager().CreateStorage(); default: throw new ArgumentException("Invalid format: " + format); }} 

Factory Methodиспользование

Page 23: Mikhail Valkov_Antipatterns

public enum StorageFormat{ File,

/* . . . */

Memory}

static void Main(string[] args){ IDataStorage storage = CreateStorage(StorageFormat.Memory); storage.Load();}

static IDataStorage CreateStorage(StorageFormat format){ switch (format) { case StorageFormat.Memory: return new FileStorageManager().CreateStorage(); /* . . . */

case StorageFormat.File: return new MemeoryStorageManager().CreateStorage(); default: throw new ArgumentException("Invalid format: " + format); }} 

Factory Methodк чему это приводит

Page 24: Mikhail Valkov_Antipatterns

private delegate IDataStorage MakeStorageHandler();

private static readonly IDictionary<StorageFormat, MakeStorageHandler> storageMaker = new Dictionary<StorageFormat, MakeStorageHandler> { { StorageFormat.File, () => new FileStorageManager().CreateStorage() }, { StorageFormat.Memory, () => new MemeoryStorageManager().CreateStorage() } };

static IDataStorage CreateStorage(StorageFormat format){ if (storageMaker.ContainsKey(format)) { return storageMaker[format](); }

throw new ArgumentException("Invalid format: " + format);} 

Factory Methodпример решения

Page 25: Mikhail Valkov_Antipatterns

public enum StyleType{ [StringValue("Grid")] Grid,

[StringValue("Grid View")] GridView,

[StringValue("Grid List")] GridList,}

public static string GetStringValue(this Enum @enum){ Type type = @enum.GetType(); MemberInfo[] memberInfo = type.GetMember(@enum.ToString());

if (!memberInfo.IsNullOrEmpty()) { object[] attributes = memberInfo[0].GetCustomAttributes(typeof(StringValueAttribute), false); if (!attributes.IsNullOrEmpty()) { return ((StringValueAttribute)attributes[0]).Value; } }

return @enum.ToString();}

 

Factory Methodработа с ключом