import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public final class Person {
private final int id;
private final String name;
private final Map knownPersons = new HashMap();
public Person(int id, String name) {
this.name = name;
this.id = id;
}
/**
* Метод возвращает объект персоны, с которой знакома данная персона
* Если персоны еще не знакомы, то текущая персона знакомится и запоминает
* В этом методе и есть весь смысл примера
*/
public Person getKnownPerson(int id) {
if (!knownPersons.containsKey(id)) {
knownPersons.put(id, new Person(id, getNameById(id)));
}
return knownPersons.get(id);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (knownPersons.size() > 0) {
Iterator iterator = knownPersons.keySet().iterator();
while (iterator.hasNext()) {
int key = iterator.next();
Person person = knownPersons.get(key);
sb.append(person.toString());
}
} else {
sb.append("no known persons");
}
return "Person [id=" + id + ", name=" + name + ", knownPersons="
+ sb + "]";
}
private String getNameById(int id) {
return id + "'s Name";
}
public static void main(String[] args) {
Person person1 = new Person(1, "Вася Петя");
Person person2 = person1.getKnownPerson(2);
Person person3 = person1.getKnownPerson(3);
System.out.println(person2.toString());
System.out.println(person3.toString());
System.out.println(person1.toString());
}
}
/**
* Output:
* Person [id=2, name=2's Name, knownPersons=no known persons]
* Person [id=3, name=3's Name, knownPersons=no known persons]
* Person [id=1, name=Вася Петя, knownPersons=
* Person [id=2,name=2's Name, knownPersons=no known persons]
* Person [id=3, name=3's Name, knownPersons=no known persons]
* ]
*/
четверг, 18 августа 2011 г.
Ленивая инициализация. Пример кода
четверг, 11 августа 2011 г.
Паттерн фабричный метод. Пример кода
//product
public interface MilkProduct {
String getName();
float getWeight();
}
//creator
//в абстрактном классе можно сделать процедуры по созданию продукта по умолчанию
//или какие-то общие действия
public abstract class MilkProductCreator {
abstract public MilkProduct getProduct();
}
//concrete product
public class Butter implements MilkProduct {
private float weight = 3.5f;
final private static String NAME = "Масло";
@Override
public float getWeight() {
return weight;
}
@Override
public String getName() {
return NAME;
}
}
//concrete product
public class SourCream implements MilkProduct {
private float weight = 1.3f;
final private static String NAME = "Сметана";
@Override
public float getWeight() {
return weight;
}
@Override
public String getName() {
return NAME;
}
}
//concrete creator
public class ButterCreator extends MilkProductCreator {
@Override
public MilkProduct getProduct() {
return new Butter();
}
}
//concrete creator
public class SourCreamCreator extends MilkProductCreator {
@Override
public MilkProduct getProduct() {
return new SourCream();
}
}
public class Application {
public static void main(String[] args) {
MilkProductCreator[] milkProductCreators = {
new ButterCreator(),
new SourCreamCreator()
};
for (MilkProductCreator milkProductCreator : milkProductCreators) {
MilkProduct milkProduct = milkProductCreator.getProduct();
System.out.printf(
"%s. Вес: %.1f кг\n",
milkProduct.getName(), milkProduct.getWeight()
);
}
}
}
/*
* Output:
* Сметана. Вес: 1,3 кг
* Масло. Вес: 3,5 кг
*/
понедельник, 8 августа 2011 г.
Паттерн Builder (Строитель). Пример кода
/**
* Интерфейс, описывающий части, из которых может состоять здание
* Методы специально не сделаны абстрактными, что бы иметь возможность
* не строить ненужные части здания
*/
public abstract class Builder {
public void buildFundament() {
}
public void buildFloor() {
}
public void buildRoof() {
}
public void buildBasement() {
}
abstract Object getBuilding();
}
public class FrameHouseBuilder extends Builder {
private FrameHouse fh = new FrameHouse();
public void buildFundament() {
fh.setPart("Фундамент. ");
}
public void buildFloor() {
fh.setPart("1 этаж. ");
}
public void buildRoof() {
fh.setPart("Двускатная крыша. ");
}
@Override
public FrameHouse getBuilding() {
return fh;
}
}
public class OfficeBuildingBuilder extends Builder {
private OfficeBuilding ob = new OfficeBuilding();
private int floors = 0;
public void buildFundament() {
ob.setPart("Фундамент. ");
}
public void buildBasement() {
ob.setPart("Подвал. ");
}
public void buildFloor() {
floors++;
ob.setPart(floors + " этаж. ");
}
public void buildRoof() {
ob.setPart("Плоская крыша. ");
}
@Override
public OfficeBuilding getBuilding() {
return ob;
}
}
public class FrameHouse {
private StringBuilder parts = new StringBuilder();
public void setPart(String part) {
parts.append(part);
}
public String getParts() {
return parts.toString();
}
}
public class OfficeBuilding {
private StringBuilder parts = new StringBuilder();
public void setPart(String part) {
parts.append(part);
}
public String getParts() {
return parts.toString();
}
}
/**
* Распорядитель. Собирает различные виды зданий
*/
public class Director {
public static FrameHouse getFrameHouse() {
FrameHouseBuilder fhb = new FrameHouseBuilder();
fhb.buildFundament();
fhb.buildFloor();
fhb.buildRoof();
return fhb.getBuilding();
}
public static OfficeBuilding getOfficeBuilding() {
OfficeBuildingBuilder fhb = new OfficeBuildingBuilder();
fhb.buildBasement();
fhb.buildFundament();
for (int i=0; i < 5; i++) {
fhb.buildFloor();
}
fhb.buildRoof();
return fhb.getBuilding();
}
}
public class Application {
public static void main(String[] args) {
FrameHouse fh = Director.getFrameHouse();
System.out.println(fh.getParts());
OfficeBuilding ob = Director.getOfficeBuilding();
System.out.println(ob.getParts());
}
}
/*
* Output:
* Фундамент. 1 этаж. Двускатная крыша.
* Подвал. Фундамент. 1 этаж. 2 этаж. 3 этаж. 4 этаж. 5 этаж. Плоская крыша.
*/
Абстрактная фабрика. Пример кода
public interface GuiFactory {
Button createButton();
Checkbox createCheckbox();
}
public interface Button extends Cloneable {
void click();
Button clone();
}
public interface Checkbox extends Cloneable {
void check();
Checkbox clone();
}
public class NixButton implements Button {
@Override
public void click() {
System.out.println("NixButton clicked");
}
@Override
public Button clone() {
return new NixButton();
}
}
public class WinButton implements Button {
@Override
public void click() {
System.out.println("WinButton clicked");
}
@Override
public Button clone() {
return new WinButton();
}
}
public class NixCheckbox implements Checkbox {
@Override
public void check() {
System.out.println("NixCheckbox checked");
}
@Override
public Checkbox clone() {
return new NixCheckbox();
}
}
public class WinCheckbox implements Checkbox {
@Override
public void check() {
System.out.println("WinCheckbox checked");
}
@Override
public Checkbox clone() {
return new WinCheckbox();
}
}
public class NixGuiFactory implements GuiFactory{
@Override
public Button createButton() {
return new NixButton();
}
@Override
public Checkbox createCheckbox() {
return new NixCheckbox();
}
}
public class WinGuiFactory implements GuiFactory {
@Override
public Button createButton() {
return new WinButton();
}
@Override
public Checkbox createCheckbox() {
return new WinCheckbox();
}
}
public enum GuiTypes {
WIN, NIX
}
final public class GuiCreator {
final Button button;
final Checkbox checkbox;
public GuiCreator(GuiFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public Button getNewButton() {
return button.clone();
}
public Checkbox getNewCheckbox() {
return checkbox.clone();
}
}
public class Application {
public static void main(String args[]) {
GuiTypes guiType = GuiTypes.WIN;
GuiFactory factory = null;
switch (guiType) {
case NIX:
factory = new NixGuiFactory();
break;
case WIN:
factory = new WinGuiFactory();
break;
default:
throw new IllegalStateException();
}
GuiCreator guiCreator = new GuiCreator(factory);
Button button = guiCreator.getNewButton();
Checkbox checkbox = guiCreator.getNewCheckbox();
button.click();
checkbox.check();
}
}
Делегирование. Пример кода
public class Hands {
public void chop() {
System.out.println("Рубить");
}
}
public class Legs {
public void jump() {
System.out.println("Прыгать");
}
}
public class Man {
private Hands hands = new Hands();
private Legs legs = new Legs();
public void chop() {
hands.chop();
}
public void jump() {
legs.jump();
}
}
пятница, 5 августа 2011 г.
Immutable-класс. Пример кода
Решил, что буду в метро, вместо творческой литературы изучать шаблоны проектирования, а что бы лучше усвоился материал, писать потом по памяти свой пример. Описание паттернов выкладывать не буду, только код.
import java.util.Date;
public final class ImmutableTest {
private final String name;
private final Date dateOfBirth;
private final String[] skills;
public ImmutableTest(String name, Date dateOfBirth, String... skills) {
this.name = name;
/*при конструировании объекта, полям присваиваются новые объекты,
*вместо ссылок
*/
this.dateOfBirth = new Date(dateOfBirth.getTime());
this.skills = skills.clone();
}
public String getName() {
return name;
}
/*
* Возвращаем новый объект Date, вместо передачи ссылки на текущий
*/
public Date getDateOfBirth() {
return new Date(dateOfBirth.getTime());
}
/*
* Возвращаем клонированный массив, вместо ссылки на объект массива
*/
public String[] getSkills() {
return skills.clone();
}
}
понедельник, 1 августа 2011 г.
Работа с Java в командной строке
Нашел отличную статью про работу с Java в командной строке. http://habrahabr.ru/blogs/java/125210/
четверг, 28 июля 2011 г.
Транзакции, управляемые приложением
В предыдущем посте я писал про транзакции, которые управляются контейнером EJB. Сейчас я продолжаю знакомство с транзакциями и выкладываю свои заметки про транзакции, управляемые приложением.
Транзакции, управляемые контейнером имеют одно ограничение - когда метод запускается, он может быть ассоциирован только с одной транзакцией или без транзакций вовсе. Если требуется иное, имеет смысл использовать транзакции, управляемые бином (bean-managed transactions).
Когда транзакции находятся под управлением приложения, можно использовать JDBC или JTA-транзакции.
JTA-транзакции позволяют работать с базами данных разных производителей. JTA-транзакции не поддерживают вложенных транзакций, т.е. нельзя стартовать новую транзакцию, пока не завершилась другая.
Для управления транзакциями используются следующие методы: begin, commit и rollback. В JDBC-транзакции метод begin опускается, т.к. Подразумевается, что транзакция стартовала перед началом работы с БД.
Метод stateless session бина должен завершить транзакцию до того, как вернет результат, в то время как stateful session bean может сохранять состояние транзакции между обращениями клиента к методу. Даже если клиент закрывал и заново открывал соединение с БД, транзакция будет существовать до тех пор, пока не будет вызван метод commit или rollback.
Если stateful session bean использует JDBC-транзакцию, то её состояние так же может сохраняться между вызовами пользователя за тем исключением, что если jdbc-соединение будет закрыто - транзакция оборвется.
В транзакциях, управляемых приложением нельзя запускать методы управления транзакциями уровня контейнера getRollbackOnly и setRollbackOnly интерфейса EJBContext. Вместо этого надо использовать методы getStatus и rollback интерфейса UserTransaction.
Пример JDBC-транзакции:
Таймаут транзакций под управлением EBJ-контейнера выставляется сервером приложений, а транзакций под управлением приложением - методом setTransactionTimeout интерфейса UserTransaction. По умолчанию таймаут равен нулю, что значит, что он никогда не наступит.
Транзакции, управляемые контейнером имеют одно ограничение - когда метод запускается, он может быть ассоциирован только с одной транзакцией или без транзакций вовсе. Если требуется иное, имеет смысл использовать транзакции, управляемые бином (bean-managed transactions).
Когда транзакции находятся под управлением приложения, можно использовать JDBC или JTA-транзакции.
JTA-транзакции позволяют работать с базами данных разных производителей. JTA-транзакции не поддерживают вложенных транзакций, т.е. нельзя стартовать новую транзакцию, пока не завершилась другая.
Для управления транзакциями используются следующие методы: begin, commit и rollback. В JDBC-транзакции метод begin опускается, т.к. Подразумевается, что транзакция стартовала перед началом работы с БД.
Метод stateless session бина должен завершить транзакцию до того, как вернет результат, в то время как stateful session bean может сохранять состояние транзакции между обращениями клиента к методу. Даже если клиент закрывал и заново открывал соединение с БД, транзакция будет существовать до тех пор, пока не будет вызван метод commit или rollback.
Если stateful session bean использует JDBC-транзакцию, то её состояние так же может сохраняться между вызовами пользователя за тем исключением, что если jdbc-соединение будет закрыто - транзакция оборвется.
В транзакциях, управляемых приложением нельзя запускать методы управления транзакциями уровня контейнера getRollbackOnly и setRollbackOnly интерфейса EJBContext. Вместо этого надо использовать методы getStatus и rollback интерфейса UserTransaction.
Пример JDBC-транзакции:
public void ship (String productId, String orderId, int quantity) {Пример JTA-транзакции:
try {
con.setAutoCommit(false);
updateOrderItem(productId, orderId);
updateInventory(productId, quantity);
con.commit();
} catch (Exception ex) {
try {
con.rollback();
throw new EJBException("Transaction failed:" +
ex.getMessage());
} catch (SQLException sqx) {
throw new EJBException("Rollback failed:" +
sqx.getMessage());
}
}
}
public void withdrawCash(double amount) {
UserTransaction ut = context.getUserTransaction();
try {
ut.begin();
updateChecking(amount);
machineBalance -= amount;
insertMachine(machineBalance);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
} catch (SystemException syex) {
throw new EJBException ("Rollback failed:" + syex.getMessage());
}
throw new EJBException ("Transaction failed:" + ex.getMessage());
}
}
Таймаут транзакций под управлением EBJ-контейнера выставляется сервером приложений, а транзакций под управлением приложением - методом setTransactionTimeout интерфейса UserTransaction. По умолчанию таймаут равен нулю, что значит, что он никогда не наступит.
Транзакции, управляемые контейнером EJB.
Enterprise beans поддерживают два типа управления транцакциями: container-managed или bean-managed. По умолчанию, если явно не задано, то используется первый, с которым я сегодня разбирался и хочу рассказать.
По сути, это просто заметки, сделанные с документации Java EE 6 Tutorial.
Container-managed транзакции упрощают разработку, т.к. за границами транзакции следит контейнер EJB. Транзакции, управляемые контейнером, могут работать как с session, так и с message-driven бинами.
Транзакция автоматически стартует перед началом запуска метода в бине и заканчивается по завершении этого метода. Container-managed транзакции не поддерживают вложенные и мульти-транзакции.
Container-managed транзакция не должна использовать методы управления транзакциями, т. к. эти операции возложены на контейнер EJB.
Существует возможность управления запуском транзакций для ejb-методов. Если внутри транцакции вызывается метод другого бина, то как должна вести себя транзакция с этим методом? На этот метод можно поставить различные ограничители принадлежности к текущей транзакции, при помощи аннотации @TransactionAttribute:
Пример:
в container-managed транзакциях существуют запрещенные методы, т.к. могут пересекаться с границами текущей транзакции:
По сути, это просто заметки, сделанные с документации Java EE 6 Tutorial.
Container-managed транзакции упрощают разработку, т.к. за границами транзакции следит контейнер EJB. Транзакции, управляемые контейнером, могут работать как с session, так и с message-driven бинами.
Транзакция автоматически стартует перед началом запуска метода в бине и заканчивается по завершении этого метода. Container-managed транзакции не поддерживают вложенные и мульти-транзакции.
Container-managed транзакция не должна использовать методы управления транзакциями, т. к. эти операции возложены на контейнер EJB.
Существует возможность управления запуском транзакций для ejb-методов. Если внутри транцакции вызывается метод другого бина, то как должна вести себя транзакция с этим методом? На этот метод можно поставить различные ограничители принадлежности к текущей транзакции, при помощи аннотации @TransactionAttribute:
- REQUIRED - если метод запущен внутри транзакции, то он является частью транзакции. Если запущен вне транзакции, то в нем стартует новая транзакция.
- REQUIRES_NEW - если метод запускается внутри транзакции, то она останавливается, запускается новая, отрабатывается, а затем продолжает работу первая. Если метод запускается самостоятельно, то просто стартует новая транзакция. Данный модификатор служит для того, что бы быть уверенным, что всегда будет запущена новая транзакция.
- MANDATORY - если метод запущен внутри транзакции, то он является её частью. Если же запускается вне транзакции, то бросается исключение TransactionRequiredException.
- NOT_SUPPORTED - если метод запускается внутри транзакции, то на время работы метода транзакция останавливается, пока не отработается метод, травзакция в которм не стартуетс, затем транзакция продолжает работу. Если метод запускается вне транзакции, то транзакция в нем не стартует. Этот атрибут увеличивает производительность, т.к. транзакции связаны с дополнительными нагрузками.
- SUPPORTS - если внутри транзакции, то является частью транзакции, если запускается самостоятельно, то транзакция не стартует.
- NEVER - Если внутри транзакции, то бросается исключение RemoteException, если вне транзакции, то метод запускается без старта транзакции.
Пример:
@TransactionAttribute(NOT_SUPPORTED)Если во время работы транзакции бросается системное исключение, то автоматом происходит откат транзакции. Управление откатом при эксепшенах приложения задается в методе setRollbackOnly интерфейса EJBContext, который обрабатывается с REQUIRED, REQUIRES_NEW, или MANDATORY атрибутами транзакции. Если данный метод не будет запущен — транзакция завершится успешно:
@Stateful
public class TransactionBean implements Transaction {
...
@TransactionAttribute(REQUIRES_NEW)
public void firstMethod() {...}
@TransactionAttribute(REQUIRED)
public void secondMethod() {...}
public void thirdMethod() {...}
public void fourthMethod() {...}
}
public void transferToSaving(double amount) throwsSession Beans поддерживают не обязательный интерфейс SessionSynchronization, который позволяет автоматически запускать методы на разных этапах выполнения транзакции: afterBegin, beforeCompletion, and afterCompletion. Первый может уведомлять сущность, что транзакция стартовала, второй запускается перед коммитом - последняя возможность сделать роллбек. Третий уведомляет, что транзакция выполнена и имеет только один булевый параметр со значением - true, если транзакция закоммичена или если роллбек - false
InsufficientBalanceException {
checkingBalance -= amount;
savingBalance += amount;
try {
updateChecking(checkingBalance);
if (checkingBalance < 0.00) {
context.setRollbackOnly();
throw new InsufficientBalanceException();
}
updateSaving(savingBalance);
} catch (SQLException ex) {
throw new EJBException
("Transaction failed due to SQLException: "
+ ex.getMessage());
}
}
в container-managed транзакциях существуют запрещенные методы, т.к. могут пересекаться с границами текущей транзакции:
- commit, setAutoCommit, и rollback методы класса java.sql.Connection
- getUserTransaction метод класса javax.ejb.EJBContext
- любой метод класса javax.transaction.UserTransaction
понедельник, 25 июля 2011 г.
Создавайте объекты только тогда, когда это необходимо
Создавать объекты надо только тогда, когда это действительно необходимо. Т.к. создание объекта является дорогостоящей операцией в плане производительности и освобождении памяти. В качестве решения проблемы можно использовать ленивую инициализацию:
public class Messages {
private List<String> messages;
public List<String> getMessages () {
if(messages == null) {
messages = new ArrayList<String>();
}
return messages;
}
}
четверг, 14 апреля 2011 г.
вторник, 12 апреля 2011 г.
О новой информации
Записывайте всё, что хотите запомнить, так вы сможете сохранить в себе гораздо больше информации. Очень полезно конспектировать, например, новый для вас материал книги. Во-первых при записи лучше запоминается, во-вторых, после прочтения книги дополнительный эффект оказывает проход по записанному вами материалу, и в-третьих, если вы что-то забудите, то, что бы освежить память, потом достаточно будет просто пробежаться по вашим записям. Я очень благодарен человеку, который дал мне когда-то этот совет.
понедельник, 11 апреля 2011 г.
Книга по SQL
Дочитал сегодня книгу "Изучаем SQL" Алана Бьюли. Считаю, что она будет полезна всем, кто хочет четко понимать основы SQL. Книга построена на примерах для MySQL, но в основных разделах рассмотрены только общие с другими СУБД конструкции, а так же описаны отличия от других систем управления БД. В книге много примеров, а так же задач для самостоятельного решения для лучшего закрепления тем, что, по крайней мере для меня, является большим плюсом.
вторник, 5 апреля 2011 г.
Отличные онлайн-тренировалки
http://sql-ex.ru - содержит обучающие и рейтинговые упражнения по SQL.
http://codingkata.org - сайт для тренировки навыков алгоритмов программирования на языках Clojure, Java, Jython, Javascript, Groovy, JRuby, JavaFX, Scala. Задачи представлены в виде забавных историй. Так же на сайте загружено множество вариантов решений от других пользователей, что позволяет сравнить их со своим кодом и сделать соответствующие выводы. Я на данный момент сдаю последнюю кату на желтый пояс. Язык сайта - английский.
http://www.topcoder.com - я еще не успел разобраться с этим сайтом. На первый взгляд сайт представляет из себя большое java(а может и не только java)-сообщество, где постоянно появляются какие-то конкурсные задания. Язык сайта - английский
Если вам известны подобного рода сайты - делитесь в комментариях.
http://codingkata.org - сайт для тренировки навыков алгоритмов программирования на языках Clojure, Java, Jython, Javascript, Groovy, JRuby, JavaFX, Scala. Задачи представлены в виде забавных историй. Так же на сайте загружено множество вариантов решений от других пользователей, что позволяет сравнить их со своим кодом и сделать соответствующие выводы. Я на данный момент сдаю последнюю кату на желтый пояс. Язык сайта - английский.
http://www.topcoder.com - я еще не успел разобраться с этим сайтом. На первый взгляд сайт представляет из себя большое java(а может и не только java)-сообщество, где постоянно появляются какие-то конкурсные задания. Язык сайта - английский
Если вам известны подобного рода сайты - делитесь в комментариях.
Подписаться на:
Сообщения (Atom)
