nov 2005 msc slide 1 first we look at a standard dos based application combining decorator &...

48
Nov 2005 1 First we look at a standard Dos based application ombining Decorator & Factory Patterns

Upload: jennifer-alexander

Post on 31-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

Nov 2005 MSc Slide

1

First we look at a standard Dos based application

Combining Decorator & Factory Patterns

Nov 2005 MSc Slide

2

class Account{private int balance;public Account(int b) {balance=b;}public Account(Account acc) {balance=acc.balance;}public int read_bal() {return balance;}public void deposit(int amt) {balance +=amt;}public void withdraw(int amt) {balance -=amt;}

}

Combining Decorator & Factory Patterns

public class Ex1{

public static void Main(){ Account a = new Account(20); int choice=1,amt=0; string temp; while(choice!=4){

Console.WriteLine();Console.WriteLine("1: Deposit");Console.WriteLine("2: Withdraw");Console.WriteLine("3: Read Bal");Console.WriteLine("4: Exit");Console.Write("Enter Choice:");

temp=Console.ReadLine(); choice=Convert.ToInt32(temp); :

switch(choice){ case 1: Console.Write("Enter Amount: "); temp=Console.ReadLine(); amt=Convert.ToInt32(temp);

a.deposit(amt); break; case 2: Console.Write("Enter Amount: "); temp=Console.ReadLine();amt=Convert.ToInt32(temp);

a.withdraw(amt); break; case 3: int b=a.read_bal(); Console.WriteLine("Balance="+b); break; }}}}}

Nov 2005 MSc Slide

5

- we introduce trace printouts

public void deposit(int amt){Cosole.WriteLine("deposit()"); balance +=amt;}

During Testing Phase

Nov 2005 MSc Slide

6

class Account{private int balance;public Account(int b) {balance=b;}public Account(Account acc) {balance=acc.balance;}public int read_bal() {Console.WriteLine(”read_bal()"); return balance;}public void deposit(int amt) {Console.WriteLine(”deposit()"); balance +=amt;}public void withdraw(int amt){ Console.WriteLine(”withdraw()"); balance -=amt;}}

Nov 2005 MSc Slide

7

•Must be removed after testing

•What if you need to retest later

•Different test phases my require different types of traces

Unsatisfactory

Alternative Solution using Decorator Pattern

Nov 2005 MSc Slide

8

Account

TestAcc SafeAcc

DecTest

Decorator Account

UML Class Diagram

Nov 2005 MSc Slide

9

class Account{private int balance;public Account(int b) {balance=b;}public Account(Account acc) {balance=acc.balance;}public int read_bal() {return balance;}public void deposit(int amt) {balance +=amt;}public void withdraw(int amt) {balance -=amt;}}

Combining Decorator & Factory Patterns

As Before

Nov 2005 MSc Slide

10

class Decorator : Account{protected Account account;public Decorator(Account acc):base(acc){

account=acc;}}

Combining Decorator & Factory Patterns

Nov 2005 MSc Slide

11

class TestAcc : Decorator{

public TestAcc(Account acc):base(acc){}

new public int read_bal(){ print("read_bal()"); return account.read_bal();}

new public void deposit(int amt){print("deposit()"); account.deposit(amt);}

new public void withdraw(int amt){ print("withdraw()"); account.withdraw(amt);}

public void print(String s){ Console.WriteLine(s);}

}

Nov 2005 MSc Slide

12

public class Ex1{

public static void Main(){ TestAcc a = new TestAcc(new Account(20)); int choice=1,amt=0; string temp; while(choice!=4){

Console.WriteLine();Console.WriteLine("1: Deposit");Console.WriteLine("2: Withdraw");Console.WriteLine("3: Read Bal");Console.WriteLine("4: Exit");Console.Write("Enter Choice:");

temp=Console.ReadLine(); choice=Convert.ToInt32(temp); :

Trace Printout

public class Ex1{

public static void Main(){ Account a = new Account(20); int choice=1,amt=0; :

After Testing we change back

•Safe Account

•Seeks confirmation before Deposit, Withdraw

We can create other decorators

class SafeAcc : Decorator{

public SafeAcc(Account acc):base(acc); {}

new public int read_bal() {Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp); if (choice==1) return account.read_bal();

else return 0;}

:

: new public void deposit(int amt){ Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp);

if (choice==1) account.deposit(amt);}

new public void withdraw(int a) { Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp);

if (choice==1) account.withdraw(a);}

}

public class Ex1{

public static void Main(){ SafeAcc a = new SafeAcc(new Account(20)); int choice=1,amt=0; : :

After Testing we change back

Nov 2005 MSc Slide

19

Confirmation Requested

public class Ex1{

public static void Main(){ Account ac=new Account(20); TestAcc a = new TestAcc(new SafeAcc(null,ac),ac); int choice=1,amt=0; : :

Can combine these

Nov 2005 MSc Slide

21Trace Printout and Confirmation Requested

Nov 2005 MSc Slide

22

public class Ex1{

public static void Main(){ Account ac=new Account(20); SafeAcc a = new SafeAcc(new TestAcc(null,ac),ac); int choice=1,amt=0; : :

Can combine these

Nov 2005 MSc Slide

23Confirmation Requested then Trace Printout

class TestAcc : Decorator{ private SafeAcc sacc;

public TestAcc(SafeAcc sacc,Account acc):base(acc) {this.sacc=sacc;}

new public int read_bal(){ print("read_bal()");

if (sacc!=null) return sacc.read_bal(); else return account.read_bal();}

new public void deposit(int amt){print("deposit()"); if (sacc!=null) sacc.deposit(amt); else account.deposit(amt);} :

To achieve this we must modify code of decorators

class SafeAcc : Decorator{ private TestAcc tacc;

public SafeAcc(TestAcc tacc,Account acc):base(acc) {this.tacc=tacc;}

new public int read_bal(){ Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp); if (tacc!=null) return tacc.read_bal(); else return account.read_bal();}:

new public void deposit(int amt){ Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp); if (tacc!=null) tacc.deposit(amt); else account.deposit(amt);}

new public void withdraw(int amt) { Console.Write("Enter 1 to confirm: "); string temp=Console.ReadLine(); int choice=Convert.ToInt32(temp); if (tacc!=null) tacc.withdraw(amt); else account.withdraw(amt);}}

1. Account a = new Account(bal);

2. SafeAcc a = new SafeAcc(null,new Account(20));

Or alternativeAccount ac=new Account(20);SafeAcc a = new SafeAcc(null,ac);

3. TestAcc a = new TestAcc(null,new Account(20));

4. Account ac=new Account(20); TestAcc a = new TestAcc(new SafeAcc(null,ac),ac);

Can add functionality by adding objectsOptions

Improve by using Factory Pattern

Factory creates an Account object based on data

In the following example base choice on user input

Better solution would be to read value from a configuration file

Could change the value in file after test etc

First We must make some minor changes to introduce Polymorphism

using System;abstract class Decorator :Account{

protected Account account;public Decorator(Account acc):base(acc){

account=acc;}

}class AccInterface{

virtual public int read_bal(){return 0;}virtual public void deposit(int amt){}virtual public void withdraw(int amt){}}

:

using System;abstract class Decorator :Account{

protected Account account;public Decorator(Account acc):base(acc){

account=acc;}

}class AccInterface{

virtual public int read_bal(){return 0;}virtual public void deposit(int amt){}virtual public void withdraw(int amt){}}

:

class Account:AccInterface{private int balance;public Account(int b) {balance=b;}public Account(Account acc) {balance=acc.balance;}override public int read_bal() {return balance;}override public void deposit(int amt) {balance +=amt;}override public void withdraw(int amt) {balance -=amt;}

}

class TestAcc : Decorator{ private SafeAcc sacc;

public TestAcc(SafeAcc sacc,Account acc):base(acc) {this.sacc=sacc;}

override public int read_bal(){ print("read_bal()");

if (sacc!=null) return sacc.read_bal(); else return account.read_bal();}

override public void deposit(int amt){print("deposit()"); if (sacc!=null) sacc.deposit(amt);

else account.deposit(amt);}

etc

public class Ex1{

public static void Main(){ Account ac=new Account(20); AccInterface a = new TestAcc(new SafeAcc(null,ac),ac); int choice=1,amt=0;etc

Now we can use Polymorphism to get the same result

Now we can use a Factory to decide type of Account

public class Ex1{

public static void Main(){ Console.WriteLine("Enter Account Type:"); Console.WriteLine("1: Normal"); Console.WriteLine("2: Test"); Console.WriteLine("3: Safe");

Console.WriteLine("4: Safe and Test"); Console.Write("Enter Choice:"); string t=Console.ReadLine();

int option=Convert.ToInt32(t); AccInterface a =

AccountFactory.createAccount(20,option); int choice=1,amt=0; (as before)

class AccountFactory{

static public AccInterface createAccount(int bal,int type){Account ac=new Account(bal);if (type==1) return ac;if (type==2) return new TestAcc(null,ac);if (type==3) return new SafeAcc(null,ac);else return new TestAcc(new SafeAcc(null,ac),ac);

} }

Nov 2005 MSc Slide

37

Input to Factory

public class Ex1{

public static void Main(){ Console.Write("Enter Balance:"); string t=Console.ReadLine();

int bal=Convert.ToInt32(t); AccInterface a = AccountFactory.createAccount(bal);

int choice=1,amt=0; : (as before)

Could also have a Factory Based on a single parameter

class AccountFactory{

static public AccInterface createAccount(int bal){if (bal < 100) return new Account(bal);else return new SafeAcc(null,new Account(bal));

} }

Nov 2005 MSc Slide

40

Exercise1:Given the class

class Counter{private int value;public Counter(int v){value=v;}public Counter(Counter cc){ value=cc.value;}public int read_value(){return value;}public void increment(){value++;}public void decrement(){ value--;}}

Now we want to decorate the Counter (similar to Account Ex)

Nov 2005 MSc Slide

41

(i) class UpperLimit extends Decorator{

same as before except increment will only increment if value <20

otherwise will print out “Too High” Hint:public void increment(){if (counter.read_value()<20)

(ii)class LowerLimit extends Decorator{

same as before except decrement will only decrement if value >0

otherwise will print out “Too Low”

(iii) Want a factory to decide on the of counter See next Dos screen

Nov 2005 MSc Slide

42

Nov 2005 MSc Slide

43

Exercise 1(b):

Now Modify the Application so the Factory is based on just an initial counter value read in from the Console:

- Values < 5 will generate a Normal Counter Object- 5-10 inclusive will generate a LowerLimit Object- 11 -15 an UpperLimit Object- Values > 15 will produce one with both an Upper & Lower Limit

Nov 2005 MSc Slide

44

Exercise2:Given the class

class Display{private String name;public Display(String n){name=n;}public Display(Display dd){ name=dd.name;}public void print(){System.out.println("\t"+name);}public void setName(String n){name=n;}}

Will Display a name:

Now we want to decorate the Display (similar to Account Ex)

Nov 2005 MSc Slide

45

Normal Display

Athlone

UpperLine ******************* Athlone

LowerLine Athlone *********************

Upper and Lower Line ******************* Athlone *********************

Nov 2005 MSc Slide

46

(a)class UpperLine extends Decorator{

print a line of ‘*’ before name

(b)class LowerLine extends Decorator{

print a line of ‘*’ after name

(c) Want a factory to decide on the of Display Type See next Dos screen

Nov 2005 MSc Slide

47

Nov 2005 MSc Slide

48