+-----------+ | Sale | +-----------+ |date | |time | +-----+-----+ |1 |содержит |1..* +-----+--------+ +---------------------+ |Sale LineItem |*описывает 1|Product Specification| +--------------+------------->+---------------------+ |quantity | |description | +--------------+ |price | +---------------------+ Шаблоны проектирования (design patterns) GRASP (General Responsibility Assignment Software Patterns) - основные шаблоны распределение обязанностей в программном обеспечении, шаблоны, описывающие фундаментальные принципы распределения обязанностей. Под шаблоном в данном контексте понимают именованную пару "проблема - решение", которая содержит рекомендации для применения в различных конкретных ситуациях. Шаблоны GRASP относятся к этапу проектирования и отвечают за взаимосвязь объектов в системе. Шаблон Information Expert решает проблему распределения обязанностей между объектами в объектно-ориентированной системе. Под обязанностью в контексте GRASP понимают определённые действия и функцию объекта. Таким образом, Information Expert даёт рекомендации, какие функции должен выполнять тот или иной объект. Решение - назначать обязанность следует информационному эксперту, то есть классу, у которого есть информация, необходимая для выполнения этой обязанности. Не всегда бывает так, что информация содержится в одном классе, чаще она распределена между различными классами, тогда каждый из этих классов будет частичным экспертом, то есть будет предоставлять только доступную ему информацию, а при общем взаимодействии будет решена общая задача. +--------------+ +--------------+| getTotal() +-------+1..*:st:=getSubTotal() +--------------+|+ t:------------+_:Sale_+--------------------------+_:SetLineItem_|+ ------> +-------+ -----> +-------+------+ || 1..1:pr:=getPrice() |v +-------+--------------+ |_:ProductSpecification| +----------------------+ Шаблон Creator решает проблему того, кто должен создавать экземпляры новых классов. Решение заключается в назначении классу B обязанностей создавать экземпляры класса A, если выполняется одно из условий: 1) класс B агрегирует объекты A; 2) класс B содержит объекты A; 3) класс B записывает экземпляры объектов A; 4) класс B активно использует объекты A; 5) класс B имеет данные инициализации, которые будут передаваться объектам A при их создании, то есть при создании объектов A класс B является экспертом. Поддерживается шаблон LowCoupling, снижаются затраты на сопровождение, обеспечивается возможность повторного использования созданных компонентов. Пример: +-------------+ +---------+ +------------------+ |_:Register_ | |_:Sale_ | |_:SaleLineItem | +------+------+ +-----+---+ +--------+---------+ :MakeLineItem : : :(quantity) : create : ++------------->++ (quantity) : || |+------------>++ || || || ++ ++ ++ : : : Шаблон Controller решает проблемы разделения интерфейса и логики в интерактивном приложении. Этот шаблон отвечает за то, к кому именно должны обращаться вызовы с View и кому контроллер должен делегировать запросы на выполнение. Контроллер должен отвечать за обработку входных системных сообщений. Под системными сообщениями понимаются события высокого уровня, генерируемые внешним исполнителем. Чтобы решить поставленную задачу, необходимо делегировать обязанности обработки системных сообщений классу, который отвечает одному из следующих условий: 1) класс представляет всю систему в целом, устройство или подсистему; 2) класс представляет сценарий определённого прецедента, в рамках которого выполняется обработка всех системных событий, который называется контроллером событий либо контроллером сеанса; для всех системных событий в рамках одного сценария предента используется один класс-контроллер; сеанс - это экземпляр взаимодействия с исполнителем; сеансы могут иметь произвольную длину, но чаще организованы в рамках одного прецедента. Контроллер - своеобразный вид интерфейса между ярусами предметной области и графического представления: 1) facade Controller (представляет всю систему, устройство или подсистему); если применяется контроллер прецедента (Use Case Controller), то для каждого прецедента должен существовать отдельный контроллер - не объект предметной области, а искусственная конструкция. enterItem(id,quantity)+---------------+ 9----------------------+_:Register | -------> +---------------+ +--------------+ |System | +--------------+ +--------------+ |endSale() | |enterItem() | |makeNewSale() | |makePayment() | |... | +--------------+ || \/ +---------------+ |Register | +---------------+ |+------- | || | | | ---------+ | +---------------+ Шаблон Low Coupling решает проблемы связности. Связность можно определить как количество точек соприкосновения классов между собой. Известно, что чем ниже связность классов, тем меньше их взаимовлияние, тем выше возможность повторного использования. Рекомендация: распределять обязанности между классами нужно таким образом, чтобы уменьшить связность. Не существует абсолютной меры для определения слишком высокой степени связности, следует руководствоваться следующим соображением: классы, которые являются достаточно общими по своей природе и с высокой степенью вероятности будут использоваться повторно в дальнейшем, должны иметь минимальную степень связности с другими классами, высокая степень связности не является проблемой, а проблемой является жёсткое связывание с неустойчивыми элементами.O ------> ----> makePayment() +-----------------+1:create() +-----------------+ ----------------+_:Register +----------------+_p:Payment_ | +---------+-------+ +-----------------+ | -----> | 2:addPayment(p) +-----------------+ +----------------------->|_:Sale_ | +-----------------+ -------> -------> makePayment()+--------------+1:makePayment()+----------+ ------------>|_:Register +---------------+_:Sale_ | +--------------+ +----+-----+ | v 1:create() +----+-----+ |_:Payment | +----------+ Шаблон High Cohesion решает общую проблему управления сложностью за счёт регулирования степени сцепления классов. Сцепление (cohesion) или функциональное сцепление - это мера связанности и сфокусированности обязанностей класса. Считается, что элемент имеет высокую степень сцепления, если его обязанности тесно связаны между собой и он не выполняет огромных объёмов работы. Класс с низкой степенью сцепления выполняет много разнородных функций или не связанных между собой обязанностей. Данный шаблон (High Cohesion) утверждает, что класс должен выполнять как можно меньше неспецифичных для него задач и иметь вполне определённую область применения. Дополнительные шаблоны GRASP Pure Fabrication (чистая синтетика) - обеспечивает реализацию шаблонов High Cohesion и Low Coupling или других принципов проектирования, если шаблон Expert не обеспечивает соответствующего решения. Решением может быть введение служебного класса, который представляет понятие конкретной предметной области, однако имеет высокую степень сцепления. Классу Sale необходимо хранить информацию в реляционной базе данных. Задача требует достаточно большого количества специализированных операций, поэтому класс Sale будет иметь низкую степень сцепления. Также класс Sale будет связан с интерфейсом базы данных, что повысит связность, кроме того, задача записи в базу данных является достаточно общей, поэтому необходимо обеспечить повторное использование кода. Решением данной проблемы является создание нового класса, ответственного за сохранение объектов некоторого вида на постоянном носителе (т. е. в базе данных). +-----------------+ |PersistentStorage| +-----------------+ |insert() | |update() | +-----------------+