Wzorce prezentacji internetowych

Transkrypt

Wzorce prezentacji internetowych
Wzorce prezentacji
internetowych
1. Model kontrolera widoku (Model View Controller).
2. Kontroler strony (Page Controller).
3. Kontroler fasady (Front Controller).
4. Szablon widoku (Template View).
5. Widok przekształcający (Transform View).
6. Widok dwuetapowy (Two Step View)
7. Kontroler aplikacji (Application Controller).
1
Model View Controller
Kontroler
Widok
Model
Obsługa interfejsu użytkownika jest rozdzielona między trzy odrębne
elementy (role).
2
Model View Controller
Model – obiekt reprezentujący dziedzinę. Posiada wszystkie dane
i udostępnia operacje nie związane z obsługą interfejsu użytkownika.
Widok – prezentacja modelu (danych) poprzez interfejs użytkownika.
Kontroler – odpowiada za interakcje z użytkownikiem – pobiera dane
i na ich podstawie modyfikuje model.
Kluczową kwestią w tym wzorcu projektowym jest rozdzielenie
danych od ich prezentacji. Rozdział pomiędzy widokiem a kontrolerem
jest wyraźny jedynie w przypadku interfejsu WWW.
3
Page Controller
Kontroler
strony
Widok
Model
Kontroler strony obsługuje żądania kierowane do konkretnej strony
lub funkcji udostępnianej przez serwis internetowy.
4
Page Controller
W ramach tego wzorca tworzony jest osobny kontroler dla każdej
strony internetowej. Kontroler strony może być zaimplementowany
zarówno w formie skryptu (np. cgi, serwlet) jak i strony (JSP, PHP, ASP,
itp.). Podstawowe obowiązki kontrolera strony to:
●
dekodowanie adresu URL i pobieranie przesłanych informacji (GET,
POST, Cookies, Sessions),
●
utworzenie i wywołanie wszelkich obiektów modelu niezbędnych do
przetworzenia danych,
●
Wybór widoku i przekazanie mu wszelkich, uprzednio
przygotowanych operacji.
5
Page Controller
class BasketController...{
public init(HttpServletRequest request){
Basket b = null;
try{
bid = Integer.parseInt(request.getParameter("bid"));
b = BasketHelper.findOrCreate(bid);
}catch(NullPointerException ex){
b = BasketHelper.createNew();
}
request.setAttribute("basket", b);
}
}
public doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
this.init(request);
RequestDispatcher dispatcher = this.getServletContext().
getRequestDispatcher("basket.jsp");
dispatcher.forward(request, response);
}
6
Page Controller
Kontrolerem może być tez strona JSP, która następnie wyświetli
przygotowany wynik. W takim przypadku zwykle przygotowanie
danych powierza się klasom pomocniczym, aby nadmiernie nie
komplikować scriptlet'ów umieszczonych w kodzie strony.
<jsp:useBean id="helper" class="controller.BasketController" />
<% helper.init(request); %>
Bardziej eleganckim rozwiązaniem jest implementacja własnego tagu.
<helper:init name="controller.BasketController" />
7
Page Controller
public class HelperTag extends TagSupport{
public static final String HELPER = "helper";
protected Object getProperty(String s) throws JspException{
Object helper = this.getHelper();
try{
Method m = helper.getClass().
getMethod(this.getter(s), null);
return m.invoke(helper, null);
}catch(Exception ex){ throw new JspException("..."); }
}
private String getter(String s) {
return "get"+s.substring(0, 1).toUpperCase()+ s.substring(1);
}
}
private Object getHelper() throws JspException {
Object helper = this.pageContext.getAttribute(HELPER);
if (helper==null) throw new JspException("...");
return helper;
}
8
Page Controller
class HelperInitTag extends HelperTag{
private String sClass;
public void setName(String s){
this.sClass = s;
}
@Override
public int doStartTag() throws JspException {
HelperController helper = null;
}
try {
helper = (HelperController)
Class.forName(this.sClass).newInstance();
} catch (Exception ex) {
throw new ApplicationException("...");
}
this.initHelper(helper);
this.pageContext.setAttribute(HELPER, helper);
return SKIP_BODY;
9
Page Controller
private void initHelper(HelperController helper){
}
}
HttpServletRequest request = (HttpServletRequest)
this.pageContext.getRequest();
HttpServletResponse response = (HttpServletResponse)
this.pageContext.getResponse();
helper.init(request, response);
Wszystkie własne tagi muszą być zadeklarowane w odpowiednim
deskryptorze tld (Tag Library Descriptor). W kodzie strony musi znaleźć
się też odpowiednia dyrektywa, np.
<%@ taglib uri="/WEB-INF/tlds/HelperTags.tld" prefix="helper" %>
10
Page Controller
class HelperGetTag extends HelperTag{
private String sProperty;
public void setProperty(String s){
this.sProperty = s;
}
}
public int doStartTag() throws JspException{
try {
this.pageContext.getOut().
print(this.getProperty(sProperty));
} catch (IOException e) {
throw new JspException("...");
}
return SKIP_BODY;
}
Przy okazji definiujemy tag wyświetlający własności.
<helper:get property="total" />
11
Front Controller
Kontroler
fasady
Akcja
abstrakcyjna
doGet()
doPost()
Akcja 1
Akcja 2
Akcja 3
Kontroler fasady obsługuje wszystkie żądania kierowane do serwisu.
Po analizie parametrów wejściowych wywoływane są odpowiednie
polecenia.
12
Front Controller
Zalety w stosunku do Page Controller:
●
prostsza konfiguracja serwera WWW. Dodawanie nowych akcji nie
wymaga zmian w konfiguracji,
●
obiekty akcji są tworzone niezależnie dla każdego żądania – brak
problemów z wielowątkowością, chyba że inne obiekty (np. obiekty
dziedziny) są współdzielone,
●
naturalna realizacja kodu wspólnego, który byłby realizowany przez
wszystkie kontrolery stron (np. obsługa błędów, autoryzacji, itp.),
●
łatwa rozbudowa dzięki dekoratorom (wzorzec Intercepting Filter).
13
Front Controller
W poniższym przykładzie kontroler fasady tworzy obiekt command na
podstawie danych zawartych w żądaniu a następnie przekierowuje do
niego sterowanie.
public class FrontServlet extends HttpServlet{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException{
FrontCommand command = this.getCommand(request);
command.init(this.getServletContext(), request, response);
command.process();
}
14
Front Controller
}
private FrontCommand getCommand(HttpServletRequest request)
throws ApplicationException{
Class c;
String sClass = "frontController." +
request.getParameter("command") + "Command";
try {
c = Class.forName(sClass);
} catch (ClassNotFoundException e) {
c = UnknownCommand.class;
}
try {
return (FrontCommand)c.newInstance();
} catch (Exception ex) {
throw new ApplicationException("...");
}
}
15
Front Controller
public abstract class FrontCommand {
protected ServletContext context;
protected HttpServletRequest request;
protected HttpServletResponse response;
public void init(ServletContext ctx,
HttpServletRequest req, HttpServletResponse res){
this.context = ctx;
this.request = req;
this.response = res;
}
abstract public void process()
throws ServletException, IOException;
}
protected void forward(String s)
throws ServletException, IOException {
RequestDispatcher dispatcher = this.context.
getRequestDispatcher(s);
dispatcher.forward(this.request, this.response);
}
16
Front Controller
class BasketCommand extends FrontCommand{
@Override
public void process() throws ServletException, IOException {
Basket b = null;
try{
int bid = Integer.parseInt(
request.getParameter("bid"));
b = BasketHelper.findOrCreate(bid);
}catch(Exception ex){
b = BasketHelper.createNew();
}
request.setAttribute("basket", b);
this.forward("/basket.jsp");
}
}
class UnknownCommand extends FrontCommand{
@Override
public void process() throws ServletException, IOException {
this.forward("/unknown.jsp");
}
}
17
Template View
Dynamiczna strona HTML jest projektowana tak jakby była stroną
statyczną. Dodatkowe informacje, generowane na podstawie żądania
klienta są umieszczone w kodzie HTML dzięki specjalnym znacznikom.
Tak przygotowany szablon jest przetwarzany w trakcie przygotowania
odpowiedzi przez serwer. Znaczniki zostają wtedy zastąpione
wynikami obliczeń, informacjami pobranymi z bazy danych, itp.
Wzorzec ten jest stosowany przez wiele różnych narzędzi (PHP, JSP,
ASP, ...), dlatego w praktyce nie istnieje potrzeba jego implementacji
a jedynie umiejętnego wykorzystania.
Podstawowa zaleta szablonów to brak wymagań dotyczących
znajomości języka programowania przez osoby projektujące interfejs
HTML.
18
Template View
Wskazówki dotyczące korzystania ze wzorca Template View:
●
nie stosujemy scriptletów – prowadzi to do wymieszania logiki
aplikacji z widokiem. W razie potrzeby należy stosować obiekty
pomocnicze,
●
unikamy wyrażeń warunkowych:
<if "isBestseller"><B></if>
<property name="price">
<if "isBestseller"></B></if>
w miarę możliwości zastępujemy przez:
<condition "isBestseller" decoration="bold">
<property name="price">
</condition>
19
Transform View
Model
przekształcenie
HTML
Widok jest tworzony poprzez przekształcenie obiektu dziedziny
w dokument HTML. Najczęściej model reprezentuje się w formie
XML'a przekształcanego za pomocą XSLT.
20
Transform View
Wybór pomiędzy Template View a Transform View jest uwarunkowany
preferencjami programistów oraz dostępnością narzędzi. Podstawowe
zalety Transform View:
●
niezależność od platformy (technologii) internetowej,
●
naturalna współpraca z danymi w formacie XML,
●
brak logiki aplikacji w widoku,
●
łatwiejsze testowanie niż Template View (nie potrzeba serwera www).
Problemy:
●
trudno zmienić ogólny wygląd strony.
21
Two Step View
Model
przekształcenie 1
HTML
Ekran
logiczny
przekształcenie 2
Widok dwuetapowy tworzy kod HTML w dwóch krokach. W pierwszym,
na podstawie obiektów dziedziny tworzony jest „logiczny obraz”
strony, który następnie jest przetwarzany do dokumentu HTML.
22
Two Step View
Widok dwuetapowy ułatwia globalną zmianę wszystkich stron
w serwisie internetowym. Najczęstsze implementacje:
●
podwójne przekształcenie XSLT. Pierwsze tworzy dokument XML
opisujący stronę, drugie generuje kod HTML.
●
opis logicznej strony przez zbiór klas, która następnie jest
przekształcana do HTML'a (w calości bądź poprzez przekształcenia
każdej z klas składowych),
●
logiczny ekran opisany poprzez wzorzec Template View nie
zawierający znaczników HTML (zwykle prowadzi to do dokumentu w
formacie XML). Przekształcenia szablonu prowadzą do strony HTML.
23
Application Controller
Kontroler aplikacji ma na celu zcentralizowanie zarządzania
dostępnymi kontrolerami i widokami. Wzorzec ten jest
wykorzystywany, gdy chcemy implementować logikę aplikacji
polegającą na prezentacji sekwencji stron www prowadzącej do
zrealizowania określonego celu. (np. złożenie zamówienia, ankieta,
test, wypełnianie zaawansowanych formularzy, itp.)
24
Application Controller
class FrontServlet...
}
public void service(HttpServletRequest request,
HttpServletResponse response){
ApplicationController controller =
this.getApplicationController(request);
String sCommand = request.getParameter("command");
DomainCommand com = controller.getDomainCommand(sCommand,
request.getParameterMap());
com.run(request.getParameterMap());
String sView = "/" + controller.getView(sCommand,
request.getParameterMap()) + ".jsp";
this.forward(sView, request, response);
}
25
Podsumowanie
Zaprezentowane wzorce przedstawiają najczęstsze metody
projektowania warstwy prezentacji internetowych. Jedną z istotnych
cech przedstawionych wzorców jest to, że można je stosować
równolegle. Umożliwia to elastyczne dostosowanie rozwiązań
informatycznych do potrzeb poszczególnych modułów aplikacji
internetowych.
26