Java/Паттерны

Материал из Викиучебника — открытых книг для открытого мира


История[править]

Идейным отцом применения шаблонов проектирования при разработке ПО считается профессор архитектуры Университета Калифорнии в Беркли Christofer Alexander.Однако по-настоящему ощутимый вклад в дело популяризации технологии шаблонов проектирования внесла изданная в 1995 году книга Design Patterns: Elements of Reusable Object-Oriented Software. Её авторы Erich Gamma, Richard Helm, Ralph Johnson и John Vlissides приложили так много усилий для распространения своих идей, что заслужили шутливое прозвище “Банда четырёх” (GoF — gang of four). В книге представлено введение в довольно сложный язык шаблонов с иллюстрациями реализации обсуждаемых шаблонов на языке C++.

Итераторы[править]

Iterator - это указатель, который в каждый момент времени указывает на один из членов списка и умеет передвигаться к следующему члену. Все классы-наследники Collection поддерживают итераторы.

Пример использования:

List arr = new ArrayList();
// ...
// Adding some elements into arr
// ...
Iterator iter = arr.iterator();
while(iter.hasNext()) {
  Object obj = iter.next();
  // ...
}

В строке 7N происходят несколько вещей:

  1. функция next - возвращает очередной элемент
  2. Ссылка на этот элемент передается в obj
  3. iter продвигается и указывает на следующий элемент

Singleton[править]

Singleton - порождающий шаблон проектирования, гарантирующий, что в однопоточном приложении будет единственный экземпляр класса с глобальной точкой доступа.

Пример[править]

class Singleton {
  private static Singleton instance;

  private Singleton() {
  }

  public static synchronized  Singleton getInstance() {
    if( instance==null ){
      instance = new Singleton();
    }
    return instance;
  }
}

Как это работает[править]

Существует только один экземпляр класса. Т.к. конструктор приватный - то чтобы получить экземпляр класса нужно обязательно вызвать статический метод getInstance, который заботится о том, что во всей системе есть только один экземпляр класса.

Когда используют Singleton?[править]

  • В том случае если мы хотим производить какое-либо действие при любом обращении к классу - это действие можно включить в функцию getInstance между строками 10N и 11N. Например добавлять к статическому счетчику единицу - тогда мы будем в любой момент точно знать сколько раз запрашивался объект Singleton.
  • В случае кеширования данных.

Factory[править]

class Person {...}
class Worker extends Person {...}
class Manager extends Person {...}

class PersonFactory {
  private boolean isWorker(int id) {...}

  private boolean isManager(int id) {...}

  public Person getPerson(int id) {
    if(isWorker(id)) {
      return new Worker(id);
    }
    if(isManager(id)) {
      return new Manager(id);
    }
    return new Person(id);
  }
}

Builder[править]

Используется для создания экземпляра класса с конкретными свойствами из-за того, что свойств может быть много и свойства объекта могут иметь сложную логику лучше вынести все это в отдельный класс

/**
** @author javawiki@ya.ru Чтв 10 Июн 2010 23:36:49 
**
**/
import java.util.*;

public class App {
	public static void main(String[] args) {
		PersonCreator pc = new PersonCreator();
		Person p1 = pc.createPerson("Вася", 10);
		Person p2 = pc.createPerson("Петя", 12);
		System.out.printf("%s= %s %s \n", p1, p1.name, p1.age);
		System.out.printf("%s= %s %s \n", p2, p2.name, p2.age);
	}
}

public class Person {
	public String name = "";
	public int age = 0;
}
// промежуточный класс для использования билдера (нужен, например, для создания нескольких перегруженных методов (например, новорожденным не нужно указывать возраст))

public class PersonCreator {
	Builder builder = new Builder();

	public Person createPerson(String name, int age) {
		builder.create();
		builder.setName(name);
		builder.setAge(age);
		return builder.getPerson();
	}
}

public class Builder {

	private Person person;

	public void create() {
		person = new Person();
	}

	public void setName(String name) {
		this.person.name = name;
	}

	public void setAge(int age) {
		this.person.age = age;
		// если, например, возраст меньше 0, то нужно выбросить исключение!
	}

	public Person getPerson() {
		return this.person;
	}
}