Тема 16. Шаблоны проектирования

Для чего нужны шаблоны проектирования

Шаблоны проектирования относятся к архитектуре программ.

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

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

Шаблоны проектирования разделены на три основные группы:

  • порождающие — призванные создавать объекты;
  • структурные — меняющие структуру взаимодействия между классами;
  • поведенческие — отвечающие за поведение объектов.

Несложно выделить и другие группы и даже антипаттерны, подсказывающие, как не надо разрабатывать ПО.

Интерфейс

Интерфейс описывает возможности классов и модулей. Он позволяет в большей степени разделить компоненты программы ( классы ) друг от друга.

Пример: Класс А использует класс В.

Без интерфейса – Классы связаны друг с другом. При изменении в 1 из классов нужно компилировать и перезапускать всю программу.

С интерфейсом - Классы взаимодействуют друг с другом через интерфейс. При изменении в 1 из классов нужно компилировать только этот класс. Также можно заменять классы без перезапуска всей программы.

Фабрика

Класс, который создает различные объекты по запросам.

Пример:

class CA{
...
}

class CB{
...
}

class ObjectFactory {

    public object CreateObject( String oType )
    {
        object o = null;

        if (oType == "CA")
            return new CA();

        if (oType == "CB")
            return new CB();

        return o;
    }
}

Отложенная инициализация

Используется для инициирования объектов объектов не при старте программы, а когда он понадобится.

Преимущества: Быстрая загрузка программы. Лучшее управление памятью.

class CWorker{
...
}

class ObjectStorage {

    // Объект vCWorker не инициирован
    static CWorker vCWorker = null;

    public static CWorker getCWorker ()
    {
          // Объект vCWorker инициируется только когда понадобится
          // если еще не инициирован.
        if (vCWorker == null)
            vCWorker = new CWorker();

        return vCWorker;
    }
}

Одиночка

Используется когда только 1 объект может быть создан. Применяется напрмер при управлении большим объемом ресурсов или аппаратурой ( файловая система ).

class CMemoryStorage
{
    static MemoryStream ms = null;

    public CMemoryStorage() {

        if ( ms != null )
            throw new Exception("Нельзя создать еще объект.");

        // 1 Gb
        ms = new MemoryStream( 1024 * 1024 * 1024  );
    }

    public void Save( byte[] buffer ){
        ms.Write( buffer, 0, buffer.Length );
    }

}

Адаптер

Часто в новом программном проекте не удается повторно использовать уже существующий код. Например, имеющиеся классы могут обладать нужной функциональностью, но иметь при этом несовместимые интерфейсы. В таких случаях следует использовать паттерн Adapter (адаптер).

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

Рассмотрим простой пример, когда следует применять паттерн Adapter. Пусть мы разрабатываем систему климат-контроля, предназначенной для автоматического поддержания температуры окружающего пространства в заданных пределах. Важным компонентом такой системы является температурный датчик, с помощью которого измеряют температуру окружающей среды для последующего анализа. Для этого датчика уже имеется готовое программное обеспечение от сторонних разработчиков, представляющее собой некоторый класс с соответствующим интерфейсом. Однако использовать этот класс непосредственно не удастся, так как показания датчика снимаются в градусах Фаренгейта. Нужен адаптер, преобразующий температуру в шкалу Цельсия.

// Уже существующий класс температурного датчика окружающей среды

class FahrenheitSensor
{

    // Получить показания температуры в градусах Фаренгейта
    public double getFahrenheitTemp() {
    double t = 32.0;
    // ... какой то код
        return t;
    }
}

class Sensor
{   
    public virtual float getTemperature();
};

class Adapter : Sensor
{   
    public
      Adapter( FahrenheitSensor p ){
          p_fsensor = p;
    }

    double getTemperature() {
        return 
          ( p_fsensor.getFahrenheitTemp() - 32.0 ) * 5.0 / 9.0;
    }

    private FahrenheitSensor p_fsensor = null;
}

Заместитель (Proxy)

Используется для замены одного обхекта другим. Работает аналогично Прокси-Серверу при доступе к интернету – Прокси-Сервер является заместителем прямого доступа к интернет.

Заместитель в архитектуре удаленного СОМ ( DCOM ) :

Дополнительная литература

http://habrahabr.ru/post/191934/ http://www.osp.ru/pcworld/2009/10/10685763/ http://andrey.moveax.ru/design-patterns/oop/ http://metanit.com/sharp/patterns/

results matching ""

    No results matching ""