Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Java_J2EE_Job_Interview_Companion

.pdf
Скачиваний:
21
Добавлен:
13.05.2015
Размер:
14.25 Mб
Скачать

270 How would you go about …?

//...

public class CD extends Goods { //..

//following methods gets called by the template method

public void addToStock() {

//database call logic to store the cd in stock table. System.out.println("CD added to stock : " + this.getDescription());

}

public void applyBarcode() {

//logic to print and apply the barcode to cd.

System.out.println("Bar code applied to cd : " + this.getDescription());

}

public void markRetailPrice() {

//logic to read retail price from the cd table and apply the retail price. System.out.println("Mark retail price for the cd : " + this.getDescription());

}

}

//...

public class Cosmetics extends Goods {

//...

public void addToStock() {

//database call logic to store the cosmetic in stock table. System.out.println("Cosmetic added to stock : " + this.getDescription());

}

public void applyBarcode() {

//logic to print and apply the barcode to cosmetic.

System.out.println("Bar code applied to cosmetic : " + this.getDescription());

}

public void markRetailPrice() {

//logic to read retail price from the cosmetic table and apply the retail price. System.out.println("Mark retail price for the cosmetic : " + this.getDescription());

}

}

Now, let’s see the calling code Shopping:

//...

public class Shopping {

//...

public static void process() throws ItemException {

//...

Item item = null;

for (item = itemIterator.firstItem(); !itemIterator.isDone(); item = itemIterator.nextItem()) {

item.prepareItemForRetail();

");

System.out.println("-----------------------------------

}

 

}

 

}

 

The output is:

 

 

 

------------------- prepareItemForRetail() -------------------------------

 

Book added to stock : Book - IT

 

Bar code applied to book : Book - IT

 

Mark retail price for the book : Book - IT

 

Scenario: The employees of XYZ Retail are at various levels. In a hierarchy, the general manager has subordinates, and also the sales manager has subordinates. The retail sales staffs have no subordinates and they report to their immediate manager. The company needs functionality to calculate salary at different levels of the hierarchy.

Solution: You can apply the composite design pattern to represent the XYZ Retail company employee hierarchy.

How would you go about …?

271

Composite design pattern: The composite design pattern composes objects into tree structures where individual objects like sales staff and composite objects like managers are handled uniformly. Refer Q61 in Java section or Q25 in Enterprise section.

/**

* Base employee class */

public abstract class Employee { private String name;

private double salary;

public Employee(String name, double salary) { this.name = name;

this.salary = salary;

}

public String getName() { return name;

}

public double getSalaries() { return salary;

}

public abstract boolean addEmployee(Employee emp); public abstract boolean removeEmployee(Employee emp); protected abstract boolean hasSubordinates();

}

<<abstract>>

Employee

*

+addEmployee()

+removeEmployee()

+hasSubordinates()

+getSalaries()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Staff

 

 

Manager

 

 

 

 

 

 

 

1

 

 

 

 

 

 

+addEmployee()

 

 

+addEmployee()

+removeEmployee()

 

 

+removeEmployee()

 

+hasSubordinates()

 

 

+hasSubordinates()

 

 

 

 

 

+getSalaries()

 

 

 

 

 

 

Leaf

 

 

 

 

 

 

 

Composite

 

 

 

 

 

 

// package & import statements

/**

* This is the Employee composite class having subordinates. */

public class Manager extends Employee {

List subordinates = null;

public Manager(String name, double salary) { super(name, salary);

}

public boolean addEmployee(Employee emp) { if (subordinates == null) {

subordinates = new ArrayList(10);

}

return subordinates.add(emp);

}

public boolean removeEmployee(Employee emp) { if (subordinates == null) {

subordinates = new ArrayList(10);

}

return subordinates.remove(emp);

}

/**

* Recursive method call to calculate the sum of salary of a manager and his subordinates, which * means sum of salary of a manager on whom this method was invoked and any employees who

* themselves will have any subordinates and so on. */

public double getSalaries() {

double sum = super.getSalaries(); //this one's salary

if (this.hasSubordinates()) {

for (int i = 0; i < subordinates.size(); i++) {

sum += ((Employee) subordinates.get(i)).getSalaries(); // recursive method call

}

}

return sum;

}

public boolean hasSubordinates() {

272

 

How would you go about …?

 

 

 

 

boolean hasSubOrdinates

= false;

 

if (subordinates != null && subordinates.size() > 0) {

 

hasSubOrdinates =

true;

 

}

 

}

return hasSubOrdinates;

 

 

 

}

 

 

/**

* This is the leaf staff employee object. staff do not have any subordinates. */

public class Staff extends Employee {

public Staff(String name, double salary) { super(name, salary);

}

public boolean addEmployee(Employee emp) {

throw new RuntimeException("Improper use of Staff class");

}

public boolean removeEmployee(Employee emp) {

throw new RuntimeException("Improper use of Staff class");

}

protected boolean hasSubordinates() { return false;

}

}

Now, let’s see the calling code Shopping:

//...

public class Shopping {

//.....

 

 

public static void process() throws ItemException {

 

//....

 

 

System.out.println("-----------------

Employee hierachy & getSalaries() recursively ---------

");

//Employee hierachy

 

 

Employee generalManager = new Manager("John Smith", 100000.00);

Employee salesManger = new Manager("Peter Rodgers", 80000.00);

Employee logisticsManger = new Manager("Graham anthony", 90000.00);

Employee staffSales1 = new Staff("Lisa john", 40000.00); Employee staffSales2 = new Staff("Pamela watson", 50000.00); salesManger.addEmployee(staffSales1); salesManger.addEmployee(staffSales2);

Employee logisticsTeamLead = new Manager("Cooma kumar", 70000.00);

Employee staffLogistics1 = new Staff("Ben Sampson", 60000.00); Employee staffLogistics2 = new Staff("Vincent Chou", 20000.00); logisticsTeamLead.addEmployee(staffLogistics1); logisticsTeamLead.addEmployee(staffLogistics2);

logisticsManger.addEmployee(logisticsTeamLead);

generalManager.addEmployee(salesManger);

generalManager.addEmployee(logisticsManger);

System.out.println(staffSales1.getName() + "-->" + staffSales1.getSalaries()); System.out.println(staffSales2.getName() + "-->" + staffSales2.getSalaries());

System.out.println("Logistics dept " + " --> " + logisticsManger.getSalaries());

System.out.println("General Manager " + " --> " + generalManager.getSalaries());

}

}

The output is:

 

How would you go about …?

273

 

 

 

---------------------

Employee hierachy & getSalaries() recursively -------------

 

Lisa john-->40000.0

 

Pamela watson--

>50000.0

 

Logistics dept

--> 240000.0

 

General Manager

--> 510000.0

 

Scenario: The purchasing staffs (aka logistics staff) of the XYZ Retail Company need to interact with other subsystems in order to place purchase orders. They need to communicate with their stock control department to determine the stock levels, also need to communicate with their wholesale supplier to determine availability of stock and finally with their bank to determine availability of sufficient funds to make a purchase.

Solution: You can apply the façade design pattern to implement the above scenario.

Façade pattern: The façade pattern provides an interface to large subsystems of classes. A common design goal is to minimize the communication and dependencies between subsystems. One way to achieve this goal is to introduce a façade object that provides a single, simplified interface.

public class StockControl {

public boolean isBelowReorderpoint(Item item) { //logic to evaluate stock level for item return true;

}

}

W i t h o u t f a c a d e

B a n k

S t o c k C o n t r o l

W h o l e S a l e r

W i t h f a c a d e

 

P u r c h a s e

E v a l u a t i o

n F a c a d e

 

B a n k

S t o c k C o n t r o l

W h o l e s a l e r

public class Bank {

public boolean hasSufficientFunds() {

//logic to evaluate if we have sufficient savings goes here return true;

}

}

public class WholeSaler {

public boolean hasSufficientStock(Item item) {

//logic to evaluate if the wholesaler has enough stock goes here return true; //to keep it simple

}

}

/**

274

How would you go about …?

 

 

 

 

* This is the facade class

 

 

*/

 

 

public class PurchaseEvaluation {

 

private StockControl stockControl = new StockControl();

 

private WholeSaler wholeSaler = new WholeSaler();

 

private Bank bank = new Bank();

 

public boolean shouldWePlaceOrder(Item item) {

 

if (!stockControl.isBelowReorderpoint(item)) {

 

return false;

 

 

}

 

 

if (!wholeSaler.hasSufficientStock(item)) {

 

return false;

 

 

}

 

 

if (!bank.hasSufficientFunds()) {

 

return false;

 

 

}

 

 

return true;

 

 

}

 

 

}

 

 

Now, let’s see the calling code or class Shopping:

 

//....

 

 

public class Shopping {

 

 

//.......

 

 

public static void process() throws ItemException {

 

//....

 

 

//----------------------

facade design pattern --------------------------------

") ;

System.out.println("--------------------

shouldWePlaceOrder----------------------------

PurchaseEvaluation purchaseEval = new PurchaseEvaluation();

boolean shouldWePlaceOrder = purchaseEval.shouldWePlaceOrder(item); System.out.println("shouldWePlaceOrder=" + shouldWePlaceOrder);

}

}

The output is:

--------------------shouldWePlaceOrder()----------------------------

shouldWePlaceOrder=true

Scenario: The purchasing department also requires functionality where, when the stock control system is updated, all the registered departmental systems like logistics and sales should be notified of the change.

Solution: This can be achieved by applying the observer design pattern as shown below:

Observer pattern: defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (aka publish-subscribe pattern)

O b s e r v e r s

1

0

0

 

 

 

 

 

 

5

0

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

1

s

t

3

r

d

 

 

Q

t

r

Q

t

r

c

N

 

o

h

t

a

i

f

 

n y

 

g

 

 

e

E a s t

W e s t

N o r t h

register

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

s

t

Q

t

r

 

 

 

 

2

n

d

Q

t r

 

 

 

 

 

 

 

3

r

d

Q

t

r

 

 

 

 

 

 

 

 

 

 

4

t

h

Q

t

r

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

r

 

 

 

y

 

 

 

 

e

 

 

f

 

 

 

 

 

 

i

 

 

e

 

 

t

 

 

t

 

 

 

 

 

is

 

o

 

 

 

g

 

g

 

N

 

 

 

n

 

e

 

 

 

 

a

 

 

r

 

 

 

 

 

h

 

 

 

 

 

 

 

c

 

 

 

 

 

 

 

 

 

 

 

 

 

1 s t Q t r = 1 0 % , 2 n d Q t r = 2 0 % , 3 Q t r = 6 0 % , 4 t h Q t r = 1 0 %

S u b j e c t

How would you go about …?

275

/**

* This is an observer (aka subscriber) interface. This gets notified through its update method. */

public interface Department {

public void update(Item item, int qty);

}

public class LogisticsDepartment implements Department { public void update(Item item, int qty) {

//logic to update department's stock goes here

System.out.println("Logistics has updated its stock for " + item.getDescription() +

" with qty=" + qty);

}

}

public class SalesDepartment implements Department { public void update(Item item, int qty) {

//logic to update department's stock goes here

System.out.println("Sales has updated its stock for " + item.getDescription() +

}

 

 

 

 

 

" with qty=" + qty);

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

-observers

 

 

 

 

«interface»

«interface»

 

Observer (aka Subscriber)

 

StockControl

 

 

 

Department

 

 

 

 

 

 

 

 

 

 

+addSubscribers()

 

 

 

+update()

 

 

 

+removeSubscribers()

 

 

 

 

 

 

 

 

 

 

 

 

 

+notify()

 

 

 

 

 

 

XYZStockControl

LogisticsDepartment SalesDepartment

+addSubscribers() +removeSubscribers() -subject+update() +update() +notify()

Subject (aka publisher)

/**

*Subject (publisher) class: when stock is updated, notifies all the

*subscribers.

*/

public interface StockControl {

public void notify(Item item, int qty); public void updateStock(Item item, int qty) ;

public boolean addSubscribers(Department dept); public boolean removeSubscribers(Department dept);

}

//… package & import statements

**

*publisher (observable) class: when stock is updated

*notifies all the subscribers.

*/

public class XYZStockControl implements StockControl{

List listSubscribers = new ArrayList(10);

//...

public boolean addSubscribers(Department dept) { return listSubscribers.add(dept);

276

How would you go about …?

}

public boolean removeSubscribers(Department dept) { return listSubscribers.remove(dept);

}

/**

* writes updated stock qty into databases */

public void updateStock(Item item, int qty) { //logic to update an item's stock goes here

notify(item, qty); //notify subscribers that with the updated stock info.

}

public void notify(Item item, int qty) {

int noOfsubscribers = listSubscribers.size(); for (int i = 0; i < noOfsubscribers; i++) {

Department dept = (Department) listSubscribers.get(i); dept.update(item, qty);

}

}

}

Now, let’s see the calling code or class Shopping:

// package & import statements

public class Shopping { //...............

public static void process() throws ItemException {

//.........

 

 

//----------------------

observer design pattern-------------------------------------------

");

System.out.println("--------------------

notify stock update----------------------------

Department deptLogistics = new LogisticsDepartment(); //observer/subscriber

 

Department salesLogistics = new SalesDepartment(); //observer/subscriber

 

StockControl stockControl = new XYZStockControl();//observable/publisher

 

//let's register subscribers with the publisher

 

stockControl.addSubscribers(deptLogistics);

 

stockControl.addSubscribers(salesLogistics);

 

//let's update the stock value of the publisher

for (item = itemIterator.firstItem(); !itemIterator.isDone(); item = itemIterator.nextItem()) { if (item instanceof CD) {

stockControl.updateStock(item, 25); } else if (item instanceof Book){

stockControl.updateStock(item, 40);

}

else {

stockControl.updateStock(item, 50);

}

}

}

}

The output is:

--------------------notify stock update----------------------------

Logistics has updated its stock for Book - IT with qty=40 Sales has updated its stock for Book - IT with qty=40 Logistics has updated its stock for CD - JAZZ with qty=25 Sales has updated its stock for CD - JAZZ with qty=25

Logistics has updated its stock for Cosmetics - Lipstick with qty=50 Sales has updated its stock for Cosmetics - Lipstick with qty=50 Logistics has updated its stock for CD - JAZZ IMPORTED with qty=25 Sales has updated its stock for CD - JAZZ IMPORTED with qty=25

Scenario: The stock control staff require a simplified calculator, which enable them to add and subtract stock counted and also enable them to undo and redo their operations. This calculator will assist them with faster processing of stock counting operations.

Solution: This can be achieved by applying the command design pattern as shown below:

How would you go about …?

277

Command pattern: The Command pattern is an object behavioral pattern that allows you to achieve complete decoupling between the sender and the receiver. A sender is an object that invokes an operation, and a receiver is an object that receives the request to execute a certain operation. With decoupling, the sender has no knowledge of the Receiver's interface. The term request here refers to the command that is to be executed. The Command pattern also allows you to vary when and how a request is fulfilled. At times it is necessary to issue requests to objects without knowing anything about the operation being requested or the receiver of the request. In procedural languages, this type of communication is accomplished via a call-back: a function that is registered somewhere to be called at a later point. Commands are the object-oriented equivalent of call-backs and encapsulate the call-back function.

C o m m a n d p a t t e r n

 

3 . in v o k e th e in v o k e r

 

 

 

 

 

 

a n d p a s s

th e

 

 

 

 

 

 

c o m m a n d a s a n

 

 

 

 

 

 

a r g u m e n t

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

T e s t

 

 

D r a w In v o k e r

 

 

 

« in t e r fa c e »

( c lie n t a p p lic a t io n )

 

 

( In v o k e r )

 

 

 

C o m m a n d

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

*

 

 

 

 

 

+ d r a w ( )

+ e x e c u t e ( )

2 . in v o k e th e c o m m a n d a n d

p a s s th e r e c ie v e r a s a n a r g u m e n t

1 . in v o k e th e r e c e iv e r

C ir c le C o m m a n d

+ e x e c u t e ( )

Cir c le

+d r a w ( )

// package & import statements

/**

* Invoker

*/

public class Staff extends Employee {

private Calculator calc = new Calculator(); private List listCommands = new ArrayList(15); private int current = 0;

public Staff(String name) { super(name);

}

S q u a r e C o m m a n d

+ e x e c u te ( )

S q u a r e

+ d r a w ( )

//...

/**

* make use of command. */

public void compute(char operator, int operand) {

Command command = new CalculatorCommand(calc, operator, operand);//initialise the calculator command.execute();

//add commands to the list so that undo operation can be performed listCommands.add(command);

current++;

}

/**

* perform redo operations */

278 How would you go about …?

public void redo(int noOfLevels) {

int noOfCommands = listCommands.size(); for (int i = 0; i < noOfLevels; i++) {

if (current < noOfCommands) {

((Command) listCommands.get(current++)).execute();

}

}

}

/**

* perform undo operations */

public void undo(int noOfLevels) {

for (int i = 0; i < noOfLevels; i++) { if (current > 0) {

((Command) listCommands.get(--current)).unexecute();

}

}

}

}

<<abstract>> Employee

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CalculatorCommand

 

 

 

 

 

 

Calculator

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+execute()

 

 

 

 

 

 

+calculate()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+unexecute()

 

 

 

 

 

 

Staff

 

 

 

 

 

«interface»

 

Command, whichdecouples

Invoker

 

 

 

1

*

 

Command

 

the invoker fromthe receiver.

 

 

 

 

+compute()

 

 

 

 

 

+execute()

 

 

 

 

 

 

+redo()

 

 

 

 

 

+unexecute()

 

 

 

 

 

 

+undo()

 

 

 

 

 

 

 

 

 

Receiver

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

**

* actual receiver of the command who performs calculation */

public class Calculator { private int total = 0;

/**

* calculates. */

public void calculate(char operator, int operand) { switch (operator) {

case '+':

total += operand; break;

case '-':

total -= operand; break;

}

System.out.println("Total = " + total);

How would you go about …?

279

}

}

/**

* command interface */

public interface Command { public void execute(); public void unexecute();

}

/**

* calculator command, which decouples the receiver Calculator from the invoker Staff */

public class CalculatorCommand implements Command { private Calculator calc = null;

private char operator; private int operand;

public CalculatorCommand(Calculator calc, char operator, int operand) { this.calc = calc;

this.operator = operator; this.operand = operand;

}

public void execute() { calc.calculate(operator, operand);

}

public void unexecute() { calc.calculate(undoOperand(operator), operand);

}

private char undoOperand(char operator) { char undoOperator = ' ';

switch (operator) { case '+':

undoOperator = '-'; break;

case '-': undoOperator = '+'; break;

}

return undoOperator;

}

}

Now, let’s see the calling code class Shopping:

//..............

public class Shopping {

//...........

public static void process() throws ItemException {

//-------------------------------

command design pattern-----------------------------------

");

System.out.println("------------

Calculator with redo & undo operations-----------------------

Staff stockControlStaff = new Staff("Vincent Chou");

 

stockControlStaff.compute('+',10);//10

 

stockControlStaff.compute('-',5);//5

 

stockControlStaff.compute('+',10);//15

 

stockControlStaff.compute('-',2);//13

 

//lets try our undo operations

undo operation : 1 level

");

System.out.println("---------------

stockControlStaff.undo(1);

undo operation : 2 levels

");

System.out.println("---------------

stockControlStaff.undo(2);

 

 

//lets try our redo operations

redo operation : 2 levels

");

System.out.println("---------------

stockControlStaff.redo(2);

 

 

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]