Немного о UML

Простыми словами о проектировании (Class diagram)

Depends On

Означает, такой вид взаимодействия объектов, когда объект A зависит от реализации объекта B, например:


public class Student { 
    public void pay(Course cource) { 
        Long cource_id = cource.getId(); 
        ... 
        } 
    }

В данном случае, мы видим зависимость объекта Student от объекта Cource. Так, если реализация объекта Cource изменится и перестанет существовать метод getId(), или скажем будет возвращать другой тип данных, то должен будет измениться и объект Student.

Обозначается такое взаимодействие следующим образом:

Стрелка указывает на объект Cource, так как от него зависит объект Student

Inherits from

Данный тип взаимодействия объектов так же не сложен в понимании, так как реализует базовые принципы объектно-ориентированного программировния (ООП) – наследование. Так, если мы имеем объект Person и от него наследуем класс Employee, то это будет неплохим примером реализации этого типа взаимодействия. В модели UML это взаимодействие будет выглядеть следующим образом:

Как мы можем видеть, стрелка указывает на объект Person, как родительский, для объекта Employee. В коде это будет выглядеть так:


class Person {
	private String name;

	public String getName() {
		return name;
	}
}
class Employee extends Person {
	private Float salary;

	public Float getSalary() {
		return salary;
	}
}

Но тут не всё так просто, существует наследование интерфейсов, и в этом плане, оно будет выглядеть почти так же, за исключением некоторых замечаний. Давайте представим это всё в виде UML:

Как можем заметить, изменилось лишь схематичное представление объектов Person и Employee.

Давайте посмотрим на то, как это выглядит в коде:


interface Person {
	String getName();
}

interface Employee extends Person {
	Float getSalary();
}

Implements interface

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


interface Person {
	String getName();
}

class Employee implements Person {
	private String name;
	private Float salary;

	public String getName() {
		return name;
	}

	public Float getSalary() {
		return salary;
	}
}

 

В конкретном случае, взаимодействие объектов можно выразить в модели UML следующим образом:

Is associated with

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

Давайте попробуем применить такой тип взаимоотношений между абстракциями. Начнём с кода:


interface PaymentManager {
	Payment pay(PaymentData data);
}

class PayPal implements PaymentManager {
	Payment pay(PaymentData data) { … }
}

class ProxyPaymentManager implements PaymentManager {
	private PaymentManager manager;

	...

	public Payment pay(PaymentData data) {
		return manager.pay(data);
	}
}

 

При условии, что на этапе проектирования, мы не уверены в том, каким образом будет реализован класс PayPal, то тут разумно будет применить взаимоотношение ассоциации. Т.е. мы имеем класс PayPal, который неким образом связан с классом ProxyPaymentManager. Как именно будет реализован класс PayPal мы не знаем (В дальнейшем, этот тип ассоциации будет определён как агрегация).

На схеме UML этот тип взаимодействия будет выглядеть следующим образом:

Как можем видеть на схеме, ProxyPaymentManager неким образом зависит от класса PayPal. Когда же команда проектировщиков вернётся к этой модели, то будет определено более точное взаимоотношение между классами.

Is an aggregate of

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


class ProxyPaymentManager implements PaymentManager {
	private PaymentManager manager;

	public ProxyPaymentManager(PaymentManager manager) {
		this.manager = manager;
	}

	public Payment pay(PaymentData data) {
		return manager.pay(data);
	}
}

Как мы можем видеть, конструктор принимает объект типа PaymentManager и не управляет жизненным циклом этого объекта. Таким образом, вид UML диаграммы будет представлен следующим образом:

Как мы можем видеть, незакрашенный ромб находится у объекта, который использует объект PaymentManager

Is composed of

Композиция – это такой вид ассоциации, при которой используемый объект полностью зависит от использующего его объекта. Давайте попробуем представить это в коде программы:


class PaymentManagerBuilder {
	private PaymentMethod method;

	public  static newManager() {
		return new PaymentManagerBuilder();
	}

	public PaymentManagerBuilder method(PaymentMethod method) {
		this.method = method;
	}

	public PaymentManager build() {
		if(this.method == null) throw new NullPointerException(“Method must not be null”);

		if(method.equals(PaymentMethod.PAYPAL)) {
			PayPal paypal = new PayPal();
			return new ProxyPaymentManager(paypal);
		}
	}
}

Код опускает частности, такие как реализация перечисления PaymentMethod и прочее.

Как мы можем видеть, объекты PayPal и ProxyPaymentManager являюся полностью зависимыми от объекта PaymentManagerBuilder, а следовательно являются его композицией. Давайте представим всё это в модели UML

uml проектирование

© JavaSE.ru