Все примеры этой главы следуют общей теме, иллюстрирующей концепцию. Мы построим простое приложение, называющуюся JavaTheater, для продажи и покупки билетов в кино. Приложение будет строится инкрементально, пример за примером, и мы будет иметь дело с адресами кинотеатров, шоу, билетами, покупателями, кредитными картами и так далее. У меня нет места, чтобы показать вам, как создавать полновесное законченное приложение, так что я сфокусируюсь на ядре функциональности.
Здесь будут классы, которые представляют постоянные сущности, такие как фильмы и шоу, и другие классы, которые реализуют большую часть логики приложения. Например, шаги, требующие реальной покупки одного или нескольких билетов на определенное шоу.
Прежде чем посмотрим на реальный код, я хочу упомянуть некоторые вещи относительно структуры исходных текстов. Все примеры находятся в директории c18 исходного кода для этой книги. Каждый поддиректорий является отдельным, самодостаточным примером, который собирается в корне поддиректория. На верхнем уровне директории каждого примера есть Ant скрипт для сборки. На этом же уровне есть директорий src, который содержит все файлы исходного кода для этого примера. Директорий src содержит поддиректории ejb-tier и rmiclient, в которых содержится код для реализации EJB и для клиентского приложения (включая JUnit тест), соответственно. Также, обратите внимание, когда вы будете собирать пример, что Ant скрипт будет создавать рабочий директорий для компиляции и сборки (смотрите комментарии в скрипте Ant более подробно), но ничего не создает и не изменяет в src директории. И, наконец, все наши классы определены в пакете javatheater, содержащем вложенные пакеты, которые тоже стоит упомянуть: javatheater.client содержит клиентское приложение; javatheater.test содержит классы JUnit тест; javatheater.ejb содержит наши EJB интерфейсы и связанные классы, а javatheater.ejb.implementation содержит классы реализации EJB.
Наш первый пример, example01, не использует никакую EJB функциональность. Это обычное и простое Java приложение, которое мы использует в качестве прототипа фундаментального класса. Наипростейший класс - это Movie, и вы можете видеть его реализацию ниже:
//: c18:example01:src:javatheater:Movie.java
//
package
javatheater;
public class
Movie
{
int
id;
String title;
public
Movie
(
int
id, String title
) {
this
.id = id;
this
.title = title;
}
public
int
getId
() {
return
id;
}
public
void
setId
(
int
id
) {
this
.id = id;
}
public
String getTitle
() {
return
title;
}
public
void
setTitle
(
String title
) {
this
.title = title;
}
public
String toString
() {
return
"["
+ id +
"] "
+ title;
}
}
// /:~
Здесь определен класс Movie, который содержит два поля: id (типа int) и title (типа String). Класс также определяет конструктор плюс сеттеры и геттеры (setters и getters) для доступа к значениям полей. Конечно, более реалистичный объект фильма должен содержать много больше информации, такой как актеры, директор, рейтинг, краткий обзор; но реализация всего этого добавит ненужную сложность в пример.
Другой класс - это Show, который также достаточно прост: у него есть id (типа int), время начала показа time (строка) и количество мест (типа int). Он также содержит ссылку на объект Movie, что означает, что у нас есть однонаправленное отношение многие к одному между показами и фильмами: фильм может быть связан с многими показами, но на одном показе может быть только один фильм. Вот реализация класса Show:
//: c18:example01:src:javatheater:Show.java
//
package
javatheater;
public class
Show
{
int
id;
Movie movie;
String showtime;
int
availableSeats;
public
Show
(
int
id, Movie movie, String showtime,
int
availableSeats
) {
this
.id = id;
this
.movie = movie;
this
.showtime = showtime;
this
.availableSeats = availableSeats;
}
public
int
getId
() {
return
id;
}
public
void
setId
(
int
id
) {
this
.id = id;
}
public
Movie getMovie
() {
return
movie;
}
public
void
setMovie
(
Movie movie
) {
this
.movie = movie;
}
public
String getShowtime
() {
return
showtime;
}
public
void
setShowtime
(
String showtime
) {
this
.showtime = showtime;
}
public
int
getAvailableSeats
() {
return
availableSeats;
}
public
void
setAvailableSeats
(
int
availableSeats
) {
this
.availableSeats = availableSeats;
}
public
String toString
() {
return
"["
+ id +
"] "
+ movie +
", "
+ showtime +
", "
+ availableSeats;
}
}
// /:~
Так как example01 это простейшее Java приложение, оно не употребляет многие службы, предоставляемые архитектурой EJB. Определенно, мы не имеет поддержки постоянства. Я не использовал JDBC для хранения и получения объектов из базы данных (что должно означать отображения объект/отношения, нечто более сложное для нашего первого примера), также в примере есть класс, называемый Storage, который эмулирует наличие постоянного хранилища данных.
//: c18:example01:src:javatheater:Storage.java
//
package
javatheater;
public class
Storage
{
private static
Storage ourInstance;
private
Movie
[]
movies;
private
Show
[]
shows;
public synchronized static
Storage getInstance
() {
if
(
ourInstance ==
null
) {
ourInstance =
new
Storage
()
;
}
return
ourInstance;
}
private
Storage
() {
movies =
new
Movie
[] {
new
Movie
(
1
,
"Return of the JNDI"
)
,
new
Movie
(
2
,
"A Bug's Life"
)
,
new
Movie
(
3
,
"Fatal Exception"
)
,
new
Movie
(
4
,
"Silence of the LANs"
)
,
new
Movie
(
5
,
"Object of my Affection"
) }
;
shows =
new
Show
[] {
new
Show
(
1
, movies
[
0
]
,
"5:30pm"
,
100
)
,
new
Show
(
2
, movies
[
0
]
,
"7:00pm"
,
300
)
,
new
Show
(
3
, movies
[
1
]
,
"6:00pm"
,
200
)
,
new
Show
(
4
, movies
[
4
]
,
"9:00pm"
,
200
) }
;
}
public synchronized
Movie findMovieById
(
int
id
) {
for
(
int
i =
0
; i < movies.length; i++
) {
Movie movie = movies
[
i
]
;
if
(
movie.id == id
)
return
movie;
}
return null
;
}
public synchronized
Movie findMovieByTitle
(
String title
) {
for
(
int
i =
0
; i < movies.length; i++
) {
Movie movie = movies
[
i
]
;
if
(
movie.title == title
)
return
movie;
}
return null
;
}
public synchronized
Movie
[]
findAllMovies
() {
return
movies;
}
public synchronized
Show findShowById
(
int
id
) {
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
if
(
show.id == id
)
return
show;
}
return null
;
}
public synchronized
Show findShowByMovie
(
Movie movie
) {
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
if
(
show.movie.id == movie.id
)
return
show;
}
return null
;
}
public synchronized
Show
[]
findAllShows
() {
return
shows;
}
}
// /:~
Этот класс реализует дизайнерский шаблон Синглетона (при котором существует только одно хранилище данных в вашей системе). Его приватный конструктор заполняет фиктивную базу данных с фильмами по Java тематике и показами. Он также предоставляет публичный метод для получения фильмов и показов из фиктивной базы данных по разным критериям. В нем нет методов для обновления нашей фальшивой базы данных, но вы вольны добавить их в качестве упражнения, если чувствуете в этом необходимость.
Последний класс в example01 - это наш главный клас, ShowListing, который просто использует хранилище для нахождения группы показов, и распечатывает их.
//: c18:example01:src:javatheater:ShowListing.java
//
package
javatheater;
public class
ShowListing
{
static
Storage storage = Storage.getInstance
()
;
public static
void
main
(
String
[]
args
) {
Show
[]
shows = storage.findAllShows
()
;
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
System.out.println
(
show
)
;
}
}
}
// /:~
Повторюсь, этот пример умышленно упрощен, но он вводит несколько фундаментальных концепций, которые мы применим при использовании EJB архитектуры: постоянство объектов, разделение сущностных классов он логики бизнес классов и связи между объектами. Плюс к этому, пример подал нам идею того, чем будет приложение, чтобы охватить все вопросы.
← | Программное обеспечение |