Паттерн проектирования "Одиночка" (Синглетон, singleton) относится к производящим шаблонам, он позволяет создавать единственный объект в системе. Создавать единственный объект в системе (и гарантировать, что будет создан только один экземпляр) иногда просто необходимо: например объекты подключения к базе данных, объекты работающие с реестрами и так далее. Наличие нескольких объектов в системе может привести к сбоям в работе приложения. Паттерн "Одиночка" помогает решить эту задачу. Для реализации данного паттерна нам нужно: во-первых, запретить создавать объекты через конструктор, сделав его приватным (так мы гарантируем, что клиентский код не сможет создать объект оператором new()), во-вторых, создать статическую переменную для хранения объекта и статический метод для возврата этого объекта. Теперь запрос объекта будем вести через имя класса и этот статический метод. Пример:
class DataBaseConnection{ //приватная статическая переменная для хранения одиночки private static DataBaseConnection connection; //приватный конструктор класса - запрещаем создавать объекты оператором new вне данного класса private DataBaseConnection(){}; //метод для возвращения единственного объекта в системе public static DataBaseConnection getInstance(){ if (connection == null){ connection = new DataBaseConnection(); } return connection; }
@Override public String toString(){return "Это объект соединения с базой данный в единственном экземпляре в системе \n";}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { //клиентский код для использования паттерна одиночки "singleton"
//при первом вызове создается объект (вызывается конструктор объекта) jTextArea1.append(DataBaseConnection.getInstance().toString()); //при повторных вызовах - возвращается уже созданный объект jTextArea1.append(DataBaseConnection.getInstance().toString()); jTextArea1.append(DataBaseConnection.getInstance().toString()); jTextArea1.append(DataBaseConnection.getInstance().toString()); jTextArea1.append(DataBaseConnection.getInstance().toString());
}
Казалось бы, все хорошо и данный код гарантирует создание единственного объекта. Проблемы могут начаться, если перенести этот код в многопоточную среду. Для того, чтобы исправить ситуацию нужно сделать метод, возвращающий объект синхронизированным:
class DataBaseConnection{ //приватная статическая переменная для хранения одиночки private static DataBaseConnection connection; //приватный конструктор класса - запрещаем создавать объекты оператором new вне данного класса private DataBaseConnection(){}; //метод для возвращения единственного объекта в системе synchronized public static DataBaseConnection getInstance(){ if (connection == null){ connection = new DataBaseConnection(); } return connection; }
@Override public String toString(){return "Это объект соединения с базой данный в единственном экземпляре в системе \n";}
}
Данный код будет хорошо работать в многопоточной среде, но он немного неэффективный в связи с наличием синхронизированного метода. В идеале синхронизация нужна только при первом вызове, далее она не нужна. Поэтому можно переделать немного этот код, поместив создание объекта в секцию синхронизации, а возврат созданного объекта оставив не синхронизированным.