Laboratorium 2
Cel:
Zapoznanie si´ z wybranymi elementami programowania obiektowego
Model obiektowy
W ramach laboratorium zostanie zbudowany model obiektowy przyk∏adowej aplikacji opisujàcej bank. Za∏o˝enia aplikacji sà nast´pujàce: "Nale˝y zbudowaç model systemu obs∏ugujàcego wybrane rodzaje kont bankowych. Bank przechowuje informacj´ o kontach jak i ich w∏aÊcicielach. Obs∏uga kont przeprowadzana jest przez pracownika banku. Budowany system ma byç ∏atwo rozszerzalny o nowe rodzaje kont."
Model logiczny systemu mo˝na przedstawiç nast´pujàco:
Nale˝y podkreÊliç, ˝e pokazany model na charakter czysto logiczny, tzn. opisane zale˝noÊci nie zawsze przek∏adajà si´ na kod w konkretnym j´zyku implementacji ale s∏u˝à do pokazania relacji jakie zachodzà mi´dzy obiektami.
W szczególnoÊci relacja agregacji mi´dzy Account i Customer jest modelowana tylko w obiekcie Account zawierajàcym dok∏adnie jeden obiekt typu Customer, ale jednoczeÊnie model niesie informacj´, ˝e ten sam obiekt Customer mo˝e przynale˝eç do jednego lub wi´cej obiektów typu Account.
W podobny sposób wyglàda relacja agregacji pomi´dzy obiektami Bank i Account. Relacja asocjacji pomi´dzy obiektami Teller i Bank jest implementowana w obiekcie Teller, ale model zawiera informacj´, ˝e z obiektu Bank mo˝e byç skojarzony z wieloma obiektami typu Teller.
Model fizyczny
W modelu fizycznym modelowane sà zagadnienia zwiàzane ju˝ z konkretnà implementacjà danego systemu. Poza obiektami z tzw. dziedziny problemu pojawiajà się obiekty zwiàzane z implementacjà. Uszczegó∏awia si´ opis poszczególnych obiektów, ich zachowanie i atrybuty.
Model fizyczny zazwyczaj jest podstawà do implementacji w wybranym j´zyku obiektowym. Bardzo cz´sto narz´dzia typu CASE u∏atwiajàce modelowanie majà mo˝liwoÊç na tym etapie wygenerowania kodu êród∏owego klas i sygnatur metod.
Uzupe∏nieniem statycznego modelu klas sà diagramy pokazujàce dynamiczne zachowanie si´ systemu.
Dopiero wszystkie elementy opisujàce zachowanie si´ systemu pozwalajà na poprawnà, zgodnà z wyobra˝eniem projektanta, implementacj´ systemu.
Implementacja systemu
W ramach laboratorium powinna zostaç dokonana implementacja przedstawionego modelu. Nale˝y wskazaç aby do obs∏ugi powodzenia operacji na koncie wykorzystaç mechanizm wyjàtków rzucanych w sytuacjach próby wykonania nieprawid∏owej operacji.
Klasa Account jest klasà abstrakcyjnà, co oznacza, ˝e mo˝na przechowywaç obiekty typu Account, natomiast w procesie kreowania instancji tego typu nale˝y pos∏u˝yç si´ konkretnà implementacjà wybranego rodzaju konta.
Przedstawione konkretne implementacje klasy Account definiujà metod´ withdraw(), w której okreÊlajà ró˝ne zasady dokonywania wyp∏aty (ró˝ne kwoty prowizji, inna wysokoÊç dopuszczalnego debetu).
Nale˝y podkreÊliç, ze wybór rodzaju konta odbywa si´ tylko na etapie jego kreacji. Korzystanie ju˝ z konta poprzez obiekt Teller dokonuje si´ bez znajomoÊci typu instancji obiektu, a jedynie na podstawie zachowania zdefiniowanego w klasie bazowej. Dzi´ki temu ∏atwo mo˝na dodawaç nowe rodzaje kont bez wp∏ywu na istniejàcy ju˝ kod dokonujàcy operacji na kontach. Wykorzystano tu w∏asnoÊci modelowania obiektowego zwiàzane z dziedziczeniem i polimorfizmem.
Przyk∏ad implementacji
Przedstawiona implementacji modelu jest przyk∏adowa. W trakcie laboratorium studenci nie powinni si´ na niej wzorowaç. Niech pracujà samodzielnie!
Cutomer.java
public class Customer {
protected String theName;
public Customer(String aName) {
theName = aName;
}
public String getName() {
return theName;
}
}
InvalidAmountException.java
public class InvalidAmountException extends Exception {
}
AccountOverdrawnException.java
public class AccountOverdrawnException extends Exception {
}
Account.java
public abstract class Account {
protected double balance;
protected Customer theCustomer;
protected Account(Customer aCustomer) {
theCustomer = aCustomer;
}
public void deposit(double amount) throws InvalidAmountException {
if (amount < 0) {
throw new InvalidAmountException();
}
balance += amount;
}
public abstract void withdraw(double amount) throws
InvalidAmountException,AccountOverdrawnException;
public double balance() {
return balance;
}
public Customer getCustomer() {
return theCustomer;
}
}
SavingAccount.java
public class SavingAccount extends Account {
protected double percentage;
public SavingAccount(Customer customer, double amount) {
super(customer);
percentage = amount;
}
public void withdraw(double amount) throws
InvalidAmountException, AccountOverdrawnException {
if (amount < 0 ) {
throw new InvalidAmountException();
}
if (balance - amount < 0) {
throw new AccountOverdrawnException();
}
balance -= amount + amount*percentage;
}
}
CheckingAccount.java
public class CheckingAccount extends Account {
protected double debit;
public CheckingAccount(Customer customer, double amount) {
super(customer);
debit = amount;
}
public void withdraw(double amount) throws
InvalidAmountException, AccountOverdrawnException {
if (amount < 0 ) {
throw new InvalidAmountException();
}
if (balance + debit - amount < 0) {
throw new AccountOverdrawnException();
}
balance -= amount;
}
}
Bank.java
import java.util.Vector;
public class Bank {
protected Vector accounts;
public Bank() {
accounts = new Vector();
}
public int addAccount(Account account) {
accounts.addElement(account);
return accounts.size();
}
public Account getAccount(int number) {
return (Account) accounts.elementAt(number-1);
}
public static void main(java.lang.String args[]) {
Bank bank = new Bank();
Teller teller = new Teller(bank);
teller.doYourWork();
}
}
Teller.java
public class Teller {
protected Bank theBank;
public Teller(Bank aBank) {
theBank = aBank;
}
public void doYourWork() {
//create customer
Customer customer = new Customer("Jan Kowalski");
//Checking account
Account checkingAccount = new CheckingAccount(customer, 10.0);
int accNo1 = theBank.addAccount(checkingAccount);
//Saving account
Account savingAccount = new SavingAccount(customer, 0.01);
int accNo2 = theBank.addAccount(savingAccount);
Account account = null;
//-------------------
account = theBank.getAccount(1);
try {
account.deposit(100.0);
account.withdraw(115.0);
}
catch(InvalidAmountException e) {
System.out.println("Wrong amount.");
}
catch(AccountOverdrawnException e) {
System.out.println("To much to withdraw.");
}
System.out.println("Balance: "+account.balance());
//-------------------
account = theBank.getAccount(2);
try {
account.deposit(100.0);
account.withdraw(90.0);
}
catch(InvalidAmountException e) {
System.out.println("Wrong amount.");
}
catch(AccountOverdrawnException e) {
System.out.println("To much to withdraw.");
}
System.out.println("Balance: "+account.balance());
}
}