Bridge = most.
Zadanie programistyczne
Smok programista ma za zadanie opracować system zapisu różnych informacji
w różny sposób. Wiadomość może być:
- zaszyfrowana
- tekstowa
Wiadomość może być zapisana:
- na konsoli
- w pliku
Rozwiązanie
- Stworzyć interface
Logger
, które określa miejsce zapisywania - Stworzyć 2 klasy implementujące – jak można zauważyć jest to prosta implementacja.
- Stworzyć interface
Message
, które określa typ wiadomości - Stworzyć 2 klasy implementujące – jak można zauważyć to każda klasa implementuje
Message
i
zawiera obiekt typuLogger
- Stworzyć klasę
Client
i sprawdzić działanie.
Utworzenie nowej klasy np. DBLogger
jest dziecinnie łatwe.
Utworzenie nowej klasy HTMLMessage
tez jest wyjątkowo łatwe.
Klasy
Pakiet db
Klasa DBLogger
package bridge.db; import bridge.localization.Logger; public class DBLogger implements Logger { @Override public synchronized void log(String msg) { writeToDB("log_base", msg); } private static void writeToDB(String nazwaPBazy, String msg) { // Do napisania } }
Klasa DerbyUtil
package bridge.db; import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; class DerbyUtil { public static final String embdriver = "EmbeddedDriver"; /** * Startuje DerbyEngine. Jeśi załadowano Embedded Driver można od razu * połączyć się z bazą danych. Jeśli załadowano ClientDriver aby połączyć * się z bazą danych należy wcześniej uruchomić NetworkServer na tym lub * zdalnym komputerze (w zależności gdzie znajduje się baza danych). Jeśli * baza danych znajduje się na innym komputerze to połączenie z nią jest * możliwe o ile na komputerze z bazą zostaną ustawione odpowiednie prawa * dostępu. Jeżeli nie zostaną ustawione możliwe jest połączenie tylko z * tego komputera, na którym baza się znajduje * * @param driverName - nazwa sterownika * @return - true -jeśli sterownik został załadowany i silnik bazy danych * Derby został uruchomiony, false - jeśli sterownik bazy danych nie został * załadowany i silnik bazy danych nie został uruchomiony */ public static boolean startDerbyEngine(String driverName) { boolean started; loadDBDriver(driverName); started = true; return started; } /** * Ładuje wskazany sterownik bazy danych * * @param driverName - nazwa sterownika do załadowania * @return - true - jeśli sterownik został załadowany, false - w przeciwnym * przypadku * @throws IllegalArgumentException - wyrzucany wyjątek */ private static boolean loadDBDriver(String driverName) throws IllegalArgumentException { if (driverName.equals("EmbeddedDriver") || driverName.equals("ClientDriver")) { try { try { Class.forName("org.apache.derby.jdbc." + driverName) .getDeclaredConstructor().newInstance((Object[]) null); } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); return false; } } else { throw new IllegalArgumentException("Niewłaściwa nazwa sterownika"); } return true; } /** * Tworzy połaczenie z wbudowaną bazą danych. Ustawia właściwości określone * w łańcuchu znaków 'properties' * * * @param dbName - nazwa bazy danych lub ścieżka do bazy danych z nazwą bazy * danych na końcu * @param properties - pary właściwości połączenia (nazwa=właściwość) * oddzielone średnikami. Średnik na początku i końcu nie są potrzebne. * @return - połączenie z bazą danych */ public static Connection connectEmbeddedDB(String dbName, String properties) { Connection conn = null; try { conn = DriverManager .getConnection("jdbc:derby:" + dbName + ";" + properties); } catch (Throwable e1) { e1.printStackTrace(); } return conn; } /** * Zamyka polecenie * * @param stat - polecenie do zamknięcia * @return - true - jeśli stat zostało zamknięta, false - w przeciwnym * wypadku */ public static boolean close(Statement stat) { if (stat != null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } return true; } /** * Zamyka połączenie * * * @param conn - połączenie do zamknięcia * @return - true - jeśli baza została zamknięta, false - w przeciwnym * wypadku */ public static boolean close(Connection conn) { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } return true; } /** * Zamyka zbiór wynikowy * * * @param rs - zamykany zbiór wynikowy * @return - true - jeśli został zamknięty, false w przeciwnym przypadku */ public static boolean close(ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } return true; } /** * Zamyka bazę o podanej nazwie * * * @param dbName - nazwa bazy do zamknięcia * @return true - jesli baza zostala zamknieta, false - w przeciwnym wypadku */ public static boolean shutdownEmbeddedDB(String dbName) { boolean shutted; boolean gotSQLExc = false; try { DriverManager .getConnection("jdbc:derby:" + dbName + ";shutdown=true"); } catch (SQLException se) { if (se.getSQLState().equals("XJ015")) { gotSQLExc = true; } } shutted = gotSQLExc; return shutted; } /** * Zatrzymuje silnik bazy danych Derby i wszystkie bazy danych, * * @return - true - jeśli silnik został zatrzymany i wszystkie bazy zostały * zamknięte, false - w przeciwnym przypadku. */ public static boolean shutdownDerbyEngine() { boolean shutted; boolean gotSQLExc = false; try { DriverManager.getConnection("jdbc:derby:;shutdown=true"); } catch (SQLException se) { if (se.getSQLState().equals("XJ015")) { gotSQLExc = true; } } shutted = gotSQLExc; return shutted; } }
Klasa MainDB
package bridge.db; import java.sql.*; class MainDB { private static final String baza = "C:\\Przyklady\\logdb"; private static final String properties = "create=true"; private static final String createTable = "CREATE TABLE logtable " + "(id INT PRIMARY KEY, logdata VARCHAR (300))"; private static final String insertData = "INSERT INTO logtable " + "VALUES(1, 'Mirka logging'),(2, 'Ula logging'),(3, 'Jacek logging')"; private static final String selectData1 = "SELECT * FROM logtable"; private static final String selectData2 = "SELECT * FROM logtable " + "WHERE id=2"; public static void main(String[] args) { DerbyUtil.startDerbyEngine(DerbyUtil.embdriver); Connection conn = DerbyUtil.connectEmbeddedDB(baza, properties); Statement stat1 = null; Statement stat2 = null; Statement stat3 = null; Statement stat4 = null; ResultSet rs1 = null; ResultSet rs2 = null; try{ stat1 = conn.createStatement(); stat1.execute(createTable); } catch (SQLException e){ e.printStackTrace(); } try{ stat2 = conn.createStatement(); stat2.execute(insertData); } catch (SQLException e){ e.printStackTrace(); } try{ stat3 = conn.createStatement(); rs1 = stat3.executeQuery(selectData1); while(rs1.next()){ System.out.println(rs1.getInt(1) + " | " + rs1.getString(2)); } } catch (SQLException e){ e.printStackTrace(); } try{ stat4 = conn.createStatement(); rs2 = stat4.executeQuery(selectData2); while(rs2.next()){ System.out.println(rs2.getInt(1) + " | " + rs2.getString(2)); } } catch (SQLException e){ e.printStackTrace(); } DerbyUtil.close(rs1); DerbyUtil.close(rs2); DerbyUtil.close(stat1); DerbyUtil.close(stat2); DerbyUtil.close(stat3); DerbyUtil.close(stat4); DerbyUtil.close(conn); DerbyUtil.shutdownEmbeddedDB(baza); DerbyUtil.shutdownDerbyEngine(); } }
Pakiet impl
Klasa Client
package bridge.impl; import bridge.message.EncryptedMessage; import bridge.message.Message; import bridge.localization.FileLogger; import bridge.localization.Logger; class Client { public static void main(String[] args) { Logger logger = new FileLogger(); Message msg = new EncryptedMessage(logger); msg.message("Test Message"); } }
Pakiet localization
Klasa ConsoleLogger
package bridge.localization; public class ConsoleLogger implements Logger { @Override public void log(String msg) { System.out.println(msg); } }
Klasa FileLogger
package bridge.localization; import java.io.*; public class FileLogger implements Logger { @Override public synchronized void log(String msg) { stringToFile("log.txt", msg, true); } private static void stringToFile(String file, String str, boolean append) { BufferedWriter bw = null; FileWriter fw = null; File f = new File(file); try { fw = new FileWriter(f, append); bw = new BufferedWriter(fw); bw.write(str); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally { close(fw); close(bw); } } private static void close(Writer w) { if (w != null) { try { w.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Klasa Logger
package bridge.localization; public interface Logger { void log(String msg); }
Pakiet message
Klasa EncryptedMessage
package bridge.message; import bridge.localization.Logger; import crypto.szyfrcezara.SzyfrCezara; public class EncryptedMessage implements Message { private final Logger logger; public EncryptedMessage(Logger logger) { this.logger = logger; } @Override public void message(String msg) { String str = SzyfrCezara.encodeMessage(msg,13); logger.log(str); } }
Klasa HTMLMessage
package bridge.message; import bridge.message.Message; import bridge.localization.Logger; public class HTMLMessage implements Message { private final Logger logger; public HTMLMessage(Logger logger) { this.logger = logger; } @Override public void message(String msg) { String str = preprocess(msg); logger.log(str); } private String preprocess(String msg) { StringBuilder sb = new StringBuilder(); sb.append("<html>"); sb.append("<body>"); sb.append("<strong>"); sb.append(msg); sb.append("/strong"); sb.append("/body"); sb.append("</html>"); return sb.toString(); } }
Klasa Message
package bridge.message; public interface Message { void message(String msg); }
Klasa TextMessage
package bridge.message; import bridge.localization.Logger; public class TextMessage implements Message { private final Logger logger; public TextMessage(Logger logger) { this.logger = logger; } @Override public void message(String msg) { String str = preprocess(msg); logger.log(str); } private String preprocess(String msg) { return msg; } }
Wynik
Uwagi
Plik derby.jar możesz znaleźć tutaj.
Ściągnij jeden z zaznaczonych plików. Po rozpakowaniu znajdziesz potrzebną bibliotekę.
Wzorzec Brigde
jest zaprojektowany tak, aby odseparować interfejs klasy od jego
implementacji. Dzięki temu można zmieniać implementacje bez potrzeby wprowadzania zmian w kodzie, który korzysta z klasy.
W pakiecie db obok klasy DBLogger
, zawierającej metodę
writeToDB
do napisania znajdują się klasy pomagające napisać taka metodę. Klasa MainDB
pokazuje utworzenie, zapisanie i pobranie bazy logów. Twoim zadaniem jest rozdzieleni kodu i napisanie metody tworzącej bazę oraz metody zapisującej do bazy, a także metody wyświetlającej dane z bazy. Jedynym założeniem kodu jest, że na dysku C: istnieje folder C:/Przyklady.
Dodatkowo umieszczona została klasa DerbyUtil
zawierająca kod niezbędny do uruchomienia klasy MainDB
.
W klasie EncryptedMessage
wykorzystujemy szyfr Cezara przedstawiony we wpisie Szyfr Cezara