// Account.java/* The Account class is an abstract super class with the default characteristics of a bank account. It maintains a balance and a current number of transactions. There are default implementation for deposit(), withdraw(), and endMonth() (prints out the end-month-summary). However the endMonthCharge() method is abstract, and so must be defined by each subclass.  This is a classic strategy, factoring common behavior up to an "abstract superclass". The resulting subclasses are very short.*/import java.util.*;public abstract class Account  {	protected double balance;		// protected = available to subclasses	protected int transactions;		public Account(double balance) {		this.balance = balance;		transactions = 0;	}		// Withdraws the given amount and counts a transaction	public void withdraw(double amt) {		balance = balance - amt;		transactions++;	}	// Deposits the given amount and counts a transaction	public void deposit(double amt) {		balance = balance + amt;		transactions++;	}	public double getBalance() {		return(balance);	}			/*	 Runs the end-month series.	 Settles the end-month-charge for the account,	 prints the balance, and resets the transaction count.	 it can settle fees and print a summary.	 Relies on the endMonthCharge() method for	 each class to implement its own charge policy.	 Then does the common account printing and maintenance.	*/	public void endMonth() {		// 1. Pop down to the subclass for their		// specific charge policy (abstract method)		endMonthCharge();						// 2. now the code common to all classes				// Get our RT class name -- just showing off		// some of Java's dynamic "reflection" stuff.		// (Never use a string like this for switch() logic.)		String myClassName = (getClass()).getName();																	System.out.println("transactions:" + transactions + 			"\t balance:" + balance + "\t(" + myClassName + ")");			 		transactions = 0; 	}	/*	 Applies the end-of-month charge to the account.	 This is "abstract" so subclasses must override	 and provide a definition. At run time, this will	 "pop down" to the subclass definition.	*/	protected abstract void endMonthCharge();   	//---- 	// Demo Code 	//---- 	 	// Allocate a Random object shared by these static methods 	private static Random rand = new Random(); 	 	// Return a new random account of a random type.	private static Account randomAccount() {				int pick = rand.nextInt(3);		Account result = null;		switch (pick) {			case 0: result = new Gambler(rand.nextInt(100)); break;			case 1: result = new NickleNDime(rand.nextInt(100)); break;			case 2: result = new Fee(rand.nextInt(100)); break;		}				/****		// Another way to create new instances -- needs a default ctor		try {			Class gClass = Class.forName("Gambler");			result = (Gambler) gClass.newInstance();		}		catch (Exception e) {			e.printStackTrace();		}		****/				return(result);	}			private static final int NUM_ACCOUNTS = 20;			// Demo polymorphism across Accounts.	public static void main(String args[]) {		//Account a = new Account(10);  // Cannot do this -- Account is abstract.				// 1. Build an array of assorted accounts		Account[] accounts = new Account[NUM_ACCOUNTS];				// Allocate all the Account objects.		for (int i = 0; i<accounts.length; i++) {			accounts[i] = Account.randomAccount();		}				// 2. Simulate a bunch of transactions		// (notice how withdraw() and deposit() just work.)		for (int day = 1; day<=31; day++) {			int accountNum = rand.nextInt(accounts.length);	// choose an account			if (rand.nextInt(2) == 0) {	// do something to that account				accounts[accountNum].withdraw(rand.nextInt(100) + 1);//Polymorphism Yay!			}			else {				accounts[accountNum].deposit(rand.nextInt(100)  + 1);			}		}				// 3. Have each account print its state		System.out.println("End of month summaries...");		for (int acct = 0; acct<accounts.length; acct++) {			accounts[acct].endMonth();	// Polymorphism Yay!		}	}// output/*End of month summaries...transactions:1	 balance:-1.0	(Fee)transactions:5	 balance:-84.0	(NickleNDime)transactions:2	 balance:43.5	(NickleNDime)transactions:1	 balance:90.0	(NickleNDime)transactions:2	 balance:89.0	(Fee)transactions:1	 balance:1.0	(Gambler)transactions:1	 balance:88.0	(NickleNDime)transactions:1	 balance:150.0	(Gambler)transactions:6	 balance:-19.5	(NickleNDime)transactions:2	 balance:-29.0	(Fee)transactions:4	 balance:226.0	(Gambler)transactions:1	 balance:86.0	(Gambler)transactions:2	 balance:70.0	(Fee)transactions:2	 balance:131.5	(NickleNDime)transactions:4	 balance:-42.5	(NickleNDime)transactions:2	 balance:-20.5	(NickleNDime)transactions:3	 balance:85.0	(Fee)transactions:1	 balance:-71.0	(Gambler)transactions:2	 balance:-175.0	(Gambler)transactions:2	 balance:-48.0	(Fee)*/}// Fee.java// An Account where there's a flat $5 fee per month.// Implements endMonth() to get the fee effect.class Fee extends Account {	public final double FEE = 5.00;		public Fee(double balance) {		super(balance);	}		public void endMonthCharge() {		withdraw(FEE);	}	}// TransactionAccount.java// An Account where there is a $0.25 fee for each transactionclass TransactionAccount extends Account {	public final double TRANSACTION_FEE = 0.25;		public TransactionAccount(double balance) {		super(balance);	}		public void endMonthCharge() {		withdraw(transactions * TRANSACTION_FEE);	}	}// NickleNDime.java// An Acccount subclass where there's a $0.50 fee per withdrawal.// Overrides withdraw() to count the withdrawals and// endMonthCharge() to levy the charge.class NickleNDime extends Account {	public final double WITHDRAW_FEE = 0.50;		private int withdrawCount;	public NickleNDime(double balance) {		super(balance);		withdrawCount = 0;;	}		public void withdraw(double amount) {		super.withdraw(amount);		withdrawCount++;	}		public void endMonthCharge() {		withdraw(withdrawCount * WITHDRAW_FEE);		withdrawCount = 0;	}	}// Gambler.java// An Account where sometimes withdrawals deduct 0// and sometimes they deduct twice the amount. No end of month fee.// Has an empty implementation of endMonthCharge,// and overrides withdraw() to get the interesting effect.class Gambler extends Account {	public final double PAY_ODDS = 0.51;			public Gambler(double balance) {		super(balance);	}		public void withdraw(double amt) {				if (Math.random()<= PAY_ODDS) {			super.withdraw(2 * amt);	// unlucky		}		else {			super.withdraw(0.0);		// lucky (still count the transaction)		}	}		public void endMonthCharge() {		// ha ha, we don't get charged anything!	}	}/*Things to notice.-Because the Account ctor takes an argument, all the subclasses need a ctorso they can pass the right value up. This chore can be avoided if the superclasshas a default ctor.-Suppose we want to forbid negative balance -- all the classes"bottleneck" through withdraw(), so we just need to implement something in that one place. Bottlenecking common code through one place is good. -Note the "polymorphism" of the demo in Account.main(). It cansend Account obects deposit(), endMonth(), etc. messages and relyon the receivers to do the right thing.-Suppose we have a "Vegas" behavior where a person withdraws 500, andslightly later deposits(50). Could implement this up in Account..public void Vegas() {	withdraw(500);	// go lose 90% of the money	deposit(50);}Depending on the class of the receiver, it will do the right thing.Exercise: trace the above on a Gambler object -- what is the sequenceof methods that execute?*/