Derive the separate implementations from the common abstraction
Create an interface/handle class that "has a" and delegates to the impl
Embellish the interface class with derived classes if desired
class Node { public int value; public Node prev, next; public Node(int i) { value = i; } } class Stack { private StackImpl impl; public Stack( String s ) { if (s.equals("array")) { impl = new StackArray(); } else if (s.equals("list")) { impl = new StackList(); } else { System.out.println("Stack: unknown parameter"); } } public Stack() { this("array"); } public void push(int in) { impl.push( in ); } public int pop() { return impl.pop(); } public int top() { return impl.top(); } public boolean isEmpty() { return impl.isEmpty(); } public boolean isFull() { return impl.isFull(); } } class StackHanoi extends Stack { private int totalRejected = 0; public StackHanoi() { super("array"); } public StackHanoi(String s) { super(s); } public int reportRejected() { return totalRejected; } public void push(int in) { if (!isEmpty() && in > top()) { totalRejected++; } else { super.push(in); } } } class StackFIFO extends Stack { private StackImpl stackImpl = new StackList(); public StackFIFO() { super("array"); } public StackFIFO(String s) { super(s); } public int pop() { while (!isEmpty()) { stackImpl.push(super.pop()); } int ret = stackImpl.pop(); while (!stackImpl.isEmpty()) { push(stackImpl.pop()); } return ret; } } interface StackImpl { void push(int i); int pop(); int top(); boolean isEmpty(); boolean isFull(); } class StackArray implements StackImpl { private int[] items; private int total = -1; public StackArray() { this.items = new int[12]; } public StackArray(int cells) { this.items = new int[cells]; } public void push(int i) { if (!isFull()) { items[++total] = i; } } public boolean isEmpty() { return total == -1; } public boolean isFull() { return total == items.length - 1; } public int top() { if (isEmpty()) { return -1; } return items[total]; } public int pop() { if (isEmpty()) { return -1; } return items[total--]; } } class StackList implements StackImpl { private Node last; public void push(int i) { if (last == null) { last = new Node(i); } else { last.next = new Node(i); last.next.prev = last; last = last.next; } } public boolean isEmpty() { return last == null; } public boolean isFull() { return false; } public int top() { if (isEmpty()) { return -1; } return last.value; } public int pop() { if (isEmpty()) { return -1; } int ret = last.value; last = last.prev; return ret; } } public class BridgeDisk { public static void main(String[] args) { Stack[] stacks = {new Stack("array"), new Stack("list"), new StackFIFO(), new StackHanoi()}; for (int i=1, num; i < 15; i++) { for (int j=0; j < 3; j++) { stacks[j].push( i ); } } Random rn = new Random(); for (int i=1, num; i < 15; i++) { stacks[3].push(rn.nextInt(20)); } for (int i=0, num; i < stacks.length; i++) { while (!stacks[i].isEmpty()) { System.out.print(stacks[i].pop() + " "); } System.out.println(); } System.out.println("total rejected is " + ((StackHanoi)stacks[3]).reportRejected()); } }