1 / 72

Continuation from last time

Continuation from last time. When to Use Inner Classes. You should use an inner class if: l ogically, the inner class should be encapsulated in the outer class. (The only place where the inner class is needed is in the outer class)

colt-turner
Download Presentation

Continuation from last time

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Continuation from last time

  2. When to Use Inner Classes • You should use an inner class if: • logically, the inner class should be encapsulated in the outer class. (The only place where the inner class is needed is in the outer class) • Using an inner class allows you to reduce the number of associations you need to make by allowing access to the outer class’s instance variables.

  3. QuitListener • We also need to make a listener for the JButton that quits our program • As usual, quit a program by using the System.exit(0) method public class QuitListener implements ActionListener{ public void actionPerformed(ActionEvent e) { System.exit(0); } }

  4. Syntax: ControlPanel public class ControlPanel extends JPanel { public ControlPanel(ColorHolder holder) { this.setLayout(new BorderLayout()); this.add(new ColorButtonRow(holder), BorderLayout.NORTH); JPanelquitPanel= new JPanel(); JButtonquitButton=new JButton(“Quit”); quitButton.addActionListener(new QuitListener()); quitPanel.add(quitButton); this.add(quitPanel, BorderLayout.SOUTH); } } Add ColorButtonRow to BorderLayout.NORTH Create a JPanel to hold quitButton, and add it with BorderLayout.SOUTH. Need to hold quitButton in its own JPanel because otherwise, the JButton will become wide enough to fill in the width of its container

  5. Syntax: MainPanel • MainPanel is straightforward • construct ColorHolder • construct ShapePanel and ControlPanel, passing reference of ColorHolder to both • Note: Two different styles of passing a panel in add – both are fine package Holder; public class MainPanelextends JPanel { Public MainPanel() { super(); this.setLayout(new BorderLayout()); // Make white default color of ColorHolder ColorHolder holder = new ColorHolder(java.awt.Color.WHITE); ShapePanel shapePanel = new ShapePanel(holder); this.add(shapePanel, BorderLayout.NORTH); this.add(new ControlPanel(holder), BorderLayout.CENTER); } }

  6. Syntax: App • Must create JFrame and MainPanel, and set them up public class App { public App() { JFrame frame= new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // pass new instance directly to add(…) frame.add(new MainPanel()); // size setting method calls elided frame.setVisible(true); frame.pack(); } public static void main(String[] argv) { new App(); } } // end of class App

  7. Holder Pattern 1/3 • Provide object that acts as holder for another object, called the subject (current color in our case) • acts as placeholder for a subject that many other objects might reference • holder object is “stable,” the instance referenced by other objects does not change • holder can change what subject it is referencing, including potentially instances of a different subclass, without affecting those objects that reference the holder itself

  8. Holder Pattern 2/3 • holder object: • contains object for which it manages changes (can also be associated with it, like our ColorHolder is with initial color). • provides one level of indirection to subject instance • provides only accessor/mutator methods

  9. Holder Pattern 3/3 • Advantages: • easily change the object that many clients reference because those objects only refer to holder • provide different interface to subject • e.g., subject may be immutable, but holder provides mutable interface • Disadvantages: • requires extra class, and thus, extra delegation (more on this later)

  10. Generic Structure of Holder 1/3 Note: Holder doesn’t have to logically contain/construct the subject – our ColorHolderis an example of the holder receiving an association to its subject during construction

  11. Generic Structure of Holder 2/3 • Holderrepresentsour ColorHolder • provides mutable interface for immutable Color by maintaining reference to correct Color instance • other objects that must reference Color can only do so using ColorHolder • Subject represent what the holder holds, i.e., a reference to a java.awt.Color which can change (if we click on a new color). Changed via mutator (set method).

  12. Generic Structure of Holder 3/3 • Clients represent ColorListenersand Shapes • modify Color • delegate the changing Color to ColorHolder • ColorHolder keeps track of current Color

  13. Delegation • Delegation occurs when one class “hands off” responsibility to another class • allow run-time flexibility not possible using static class relationships like inheritance or containment • message can be sent to many objects, or augmented, each time it is forwarded • thus, provides extra flexibility and extensibility • e.g., button class delegates responses to its listener class • Used in every design pattern we will see

  14. Delegation • General structure of Delegation on right • Here, Client can be delegated in two ways: • to ObjectA or ObjectB directly • to ObjectC via Intermediate

  15. Another Example: ShapeMover • Now we want to model movable hexagons! Here’s the spec: • Design a frame with two hexagons and a grid of buttons. The two hexagons should be colored and placed differently to distinguish them. The buttons should be labeled “Move Up”, Move Down”, “Move Left”, and “Move Right”. Clicking on a button moves the current hexagon in the direction denoted by the button. Clicking on a hexagon makes the hexagon the current hexagon.

  16. Specification Analysis • Some things should be simple: • frame • grid • buttons • hexagon • More difficult things: • concept of a current hexagon • making a moving hexagon

  17. MovingHexagon MoveLeftListener MoveRightListener MoveUpListener MoveDownListener Current Hexagon: Simple Idea • First idea: Give all button listeners a reference to the hexagon they control • Problems: • when current hexagonchanges, all buttons need to reset their references • no nice way of knowing if a hexagon clicked on is new or not, so with every mouse click, all references to hexagon must be updated

  18. The Proxy Pattern 1/2 • Current hexagon sounds like current color from the holder pattern example! • could use a HexagonHolder… • hexagons would put reference to themselves in holder when clicked on • buttons would get current hexagon from holder and call messages on it • From a design perspective, gives a lot of work to the buttons • would like to avoid having buttons get current hexagon from the holder in order to call methods on it

  19. The Proxy Pattern 2/2 • Alternative: Use a Proxy! (Which you’ll be doing in Tetris!) • Proxy acts on behalf of another subject • proxy has a reference to the actual instance of subject • that reference can change • all clients know only proxy; proxy only knows subject • proxy has methods that match those of subject (but not necessarily all of the subject’s methods) • clients call methods on proxy which forwards them to subject • let’s us control what methods can be called on the underlying object that the proxy models

  20. MovingHexagon MovingHexagonProxy MoveLeftListener MoveRightListener MoveUpListener MoveDownListener Current Hexagon: Using Proxy 1/2

  21. Current Hexagon: Using Proxy 2/2 • MovingHexagonProxy acts on behalf of MovingHexagon; another example of delegation • When the JButton associated with the MoveUpListener is clicked, it calls moveUp() on proxy, which in turn calls moveUp() on hexagon (hooray for delegation!). • When hexagon is clicked, it sets proxy’s reference to itself • listeners don’t need to change their references

  22. Design:MovingHexagonProxy • analyze program and come up with a class diagram • Note this time we don’t use a separate ControlPanel class since BorderLayout suffices – design choice • All instances of MovingHexagonknow about MovingHexagonProxy, but MovingHexagonProxyonly knows about one MovingHexagonat a time • Note: Only showing BorderLayout; other LayoutManagers elided

  23. Design of the MovingHexagonProxy • MovingHexagonProxy class needs a method to set its MovingHexagon • Needs moveUp(), moveDown(), moveLeft(), and moveRight() methods to call on its MovingHexagon • e.g., moveUp() will call MovingHexagon’smoveUp() method

  24. Syntax:MovingHexagonProxy public void moveUp() { _movingHexagon.moveUp(); } public void moveDown() { _movingHexagon.moveDown(); } public void moveLeft() { _movingHexagon.moveLeft(); } public void moveRight() { _movingHexagon.moveRight(); } } // end of class MovingHexagonProxy package Proxy; public class MovingHexagonProxy { private MovingHexagon _movingHexagon; /* constructor doesn’t need to do anything because the containing class will call setHexagon(...) in its constructor to set the default hexagon in _movingHexagon */ public MovingHexagonProxy() {} // Let us change the current hexagon public void setHexagon(MovingHexagon hexagon) { _movingHexagon = hexagon; }

  25. TheMoveButtons public class MoveLeftListener implements ActionListener{ private ShapePanel _panel; private MovingHexagonProxy _proxy; public MoveLeftListener(ShapePanel panel, MovingHexagonProxyproxy) { _panel=panel; _proxy=proxy; } public void actionPerformed(ActionEvent e) { _proxy.moveLeft(); _panel.repaint(); } } • Listeners are simple! • make an ActionListenerfor each direction • You get the idea…

  26. DesigningMovingHexagon • MovingHexagon will be subclass of PolygonShape, adding extra capabilities • It will store reference to MovingHexagonProxyand tell proxy to update the reference to itself as current hexagon when clicked • moveDown() method • method should move hexagon down by, say, 25 pixels • first get the old location and translate down by 25 pixelsdouble newY = this.getY() + 25; • then actually move the point this.setLocation(this.getX(), newY); • And other move methods are similar.

  27. Syntax: MovingHexagon package Proxy; public class MovingHexagon extends PolygonShape { private MovingHexagonProxy _proxy; public MovingHexagon(MovingHexagonProxy proxy) { super(6); //6 to be a hexagon _proxy = proxy; this.setSize(50,50); } public void react() { _proxy.setHexagon(this); } public void moveDown() { double newY = this.getY() + 25; this.setLocation(this.getX(), newY); } public void moveUp(){ //remember, origin is in top-left corner of panel! double newY = this.getY() – 25; this.setLocation(this.getX(), newY); } public void moveLeft() { double newX = this.getX() – 25; this.setLocation(newX, this.getY()); } public void moveRight() { double newX = this.getX() + 25; this.setLocation(newX, this.getY()); } }

  28. MoveButtonGrid • Just instantiates buttons and adds them to the layout. • Again, buttons are added to their own JPanels so that they do not fill the whole space of the container and are reasonably sized package Proxy; public class MoveButtonGrid extends JPanel { public MoveButtonGrid(MovingHexagonProxy proxy,ShapePanel panel) { super(); this.setLayout(new GridLayout(0,3)); //Create empty space between buttons done foraesthetic reasonsthis.add(Box.createHorizontalGlue()); //Add button JPanelmoveUpPanel = new JPanel(); JButtonmoveUp = new JButton("Move Up"); moveUp.addActionListener(new MoveUpListener(panel, proxy)); moveUpPanel.add(moveUp); this.add(moveUpPanel); //And so on… this.add(Box.createHorizontalGlue()); JPanelmoveLeftPanel= new JPanel(); JButtonmoveLeft = new JButton("Move Left"); moveLeft.addActionListener(new MoveLeftListener(panel, proxy)); moveLeftPanel.add(moveLeft); this.add(moveLeftPanel); //etc. } }

  29. ShapePanel • Instantiates the MovingHexagons and colors and positions them • Sets the proxy to one of the hexagons. package Proxy; public class ShapePanel extends JPanel { private MovingHexagon _hex1, _hex2; public ShapePanel(MovingHexagonProxy proxy) { super(); this.setBackground(java.awt.Color.darkGray); _hex1 = new MovingHexagon(proxy); _hex1.setColor(java.awt.Color.RED); _hex1.setLocation(50, 250); _hex2 = new MovingHexagon(proxy); _hex2.setColor(java.awt.Color.GREEN); _hex2.setLocation(400, 251); //put a default shape in the proxy proxy.setHexagon(_hex1); //set size, other initializations elided } //MouseListener, same pattern of testing containment of //containment of point in shapes as in previous //holding example, then calls repaint. //paintComponent elided... }

  30. MainPanel package Proxy; public class MainPanel extends JPanel { public MainPanel() { super(new BorderLayout()); MovingHexagonProxy proxy = new MovingHexagonProxy(); ShapePanel shapePanel = new ShapePanel(proxy); MoveButtonGrid moveButtonGrid = new MoveButtonGrid(proxy, shapePanel); this.add(shapePanel, BorderLayout.NORTH); this.add(moveButtonGrid, BorderLayout.CENTER); JPanel quitPanel = new JPanel(); JButton quitButton = new JButton(“Quit”); quitButton.addActionListener(new QuitListener()); quitPanel.add(quitButton); this.add(quitPanel, BorderLayout.SOUTH); //size setting, ect. Elided } } • Just instantiates theShapePanel,MoveButtonGrid,MovingHexagonProxy,andJButtonto quit the App.

  31. App • Same as usual… package Proxy; public class App{ public App() { JFrame frame = new JFrame(“Super Mover!”);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //add new instance of top-level to Frame frame.add(new MainPanel()); frame.pack(); frame.setVisible(true); //size setting, main line etc. elided } }

  32. Holder vs. Proxy • Notice the similarity between Proxy pattern and simpler Holder pattern • difference is in modeling. • Holder will usually contain subject that clients can access (get) and send messages to directly • Clients access/set the subject directly via simple accessor/mutator methods • This lets clients call any public method defined by subject on instance of that subject • Proxy knows about subject that clients can call methods on indirectly by way of proxy • Lets proxy limit the methods that can be indirectly called on the subject it models

  33. ClientA ClientB Proxy ClientC Subject Generic Structure of Proxy • Proxy represents our MovingHexagonProxy • provides indirect access to the Subject for the clients • acts on behalf of MovingHexagon—an example of delegation • Subject represents the Proxy’s reference to the current MovingHexagon. When a MovingHexagon is clicked on, it sets the proxy’s reference to itself. • Clients represent Jbuttons • indirectly moves the current MovingHexagon through the MovingHexagonProxy • buttons don’t need to change their references when the current MovingHexagon is changed.

  34. Design Patterns… • Serve as examples of good design • there are no “hard and fast” rules • there are concrete trade-offs to think about • they are tools to help you build your own designs • Provide common vocabulary to discuss design at a more abstract level • give us a concise way to describe complex object interaction • discuss design at a higher level because we do not need to describe every object in the program • Must be adapted to your program specification • may need to add extra relationships to your structure to augment a design pattern. • may need to create a new pattern because none exists that exactly fits your needs. • Should be used in moderation • consider trade-offs carefully before using a pattern. • consider added complexity—is it needed in your model?

  35. Lecture 14 Recursion

  36. The Head TAs Like Cookies • They would each like to have one of these cookies: • How many ways can they distribute the cookies among themselves? • the first HTA who picks has three choices • only two choices are left for the second HTA • the last HTA has to take what remains (poor Greg!)

  37. The Head TAs Like Cookies • Thus we have six different ways the HTAs can choose cookies (3! = 3 x 2 x 1 = 6) • What if we wanted to solve this problem for all CS15 TAs? All CS15 students?

  38. Factorial Function • Model this problem mathematically: factorial (n!) calculates the total number of unique permutationsofnitems • Small examples: 1! = 1 3! = 3*2*1 = 6 5! = 5*4*3*2*1 = 120 2! = 2*1 = 2 4! = 4*3*2*1 = 24 • Iterative definition: n! = n * (n-1) * (n-2) * … * 1 • Recursive definition: n! = n * (n-1)! for n>=0 and 0! = 1

  39. Recursion (1/2) • Models problems that are self-similar • decompose a whole task into smaller, simpler sub-tasks that are similar • thus, each subtask can be solved by applying a similar technique • Whole task solved by combining solutions to sub-tasks • special form of divide and conquer

  40. Recursion (2/2) • Task is defined in terms of itself • In Java, modeled by a method that calls itself, but each time with a simpler case of the problem – Java will bookkeep each invocation of the same method just as it does for nested methods that differ, so there is no confusion • requires base case (case simple enough to be solved directly, without recursion) to end recursion; otherwise infinite recursion and StackOverFlow Exception • what is the base case of the factorial problem? • Often you combine the results from the separate invocations

  41. Coding Factorial Function Recursively • Recursive algorithm • note factorial method assumes num >= 0 • such assumptions are commonly called preconditions and should be documented (or better yet, tested for, see code example) • Number of times method is called is called depth of recursion • what is depth of (4!)? public class RecursiveMath{ //instance variables, other code elided public long factorial (int num) { if (num < 0){ System.out.println(“Input must be negative”); return -1; // Must return something, so let’s // return -1 for invalid input } long result = 0; if (num == 0){ // base case: 0! = 1 result = 1; } else{ //general case result = num * this.factorial(num - 1); } return result; }

  42. If you want to know more about recursion...

  43. Towers of Hanoi • Game invented by French mathematician Edouard Lucas in 1883 • Goal: move tower of n disks, each of a different size, from left-most peg to right-most peg • Rule 1: no disk can be placed on top of a smaller disk • Rule 2: only one disk can be moved at once

  44. Pseudocode for Towers of Hanoi (1/2) • Try solving for 5 non-recursively… • One disk: • move diskto final pole • Two disks: • use one disk solution to move top disk to intermediate pole • use one disk solution to move bottom disk to final pole • use one disk solution to move top disk to final pole • Three disks: • use two disk solution to move top disksto intermediate pole • use one disk solution to move bottom disk to final pole • use two disk solution to move top disks to final pole

  45. Pseudocode for Towers of Hanoi (2/2) • In general (for n disks) • use n-1 disk solution to move top disks to intermediate pole • use one disk solution to move bottom disk to final pole • use n-1 disk solution to move top disks to final pole • Note: can have multiple recursive calls in a method

  46. Lower level pseudocode //n is number of disks, src is starting pole, //dst is finishing pole public void hanoi(int n, Pole src, Pole dst){ if (n==1) { this.move(src, dst); } else { Pole other = this.otherPole(src, dst); this.hanoi(n-1, src, other); this.move(src, dst); this.hanoi(n-1, other, dst); } } public Pole otherPole(Pole p1, Pole p2){ //returns the pole that is neither p1 nor p2 } • public void move(Pole src, Pole dst){ • //take the top disk on the pole src and make • //it the top disk on the pole dst • That’s it! otherPole and move are fairly simple methods, so this is not much code. • But try hand simulating this when n is greater than 4! Whoo boy, is it tough! • The iterative solution is far more complex, and much harder to understand

  47. Call Out the Turtles (1/2) • Fractals: branch of mathematics developed by mathematician Benoit Mandelbrot whose principle characteristic is self-similarity - natural for recursion • check out http://matek.hu/xaos/doku.php ! • Many examples of simpler, non-fractal, but still self-similar shapes composed of smaller, simpler copies of some pattern • spiral, tree, and snowflake • We can draw these using Turtle graphics

  48. Call Out the Turtles (2/2) • Let’s start with the simplest: a spiral The spiral starts at a particular point. It is made of successively shorter lines, each line at a given angle to the previous one. The user can specify the length of the first side (the longest one), the spiral’s angle, and the amount by which to decrement the spiral’s side in each step

  49. Designing Spiral Class (1/2) • Spiral class defines single draw method • uses turtle to draw, so class needs reference to turtle instance • From spec, parameters to control its properties: • position at which spiral starts is turtle’s position • length of spiral’s starting slide • angle between successive line segments • amount to change length of spiral’s side at each step • Note: this info is passed to each invocation of recursive method, so next method call depends on previous one

  50. Designing Spiral Class (2/2) public class Spiral { private Turtle _turtle; private double _angle; private int _lengthDecrement; public Spiral(Turtle myTurtle, double myAngle, int myLengthDecrement) { _turtle = myTurtle; _angle = myAngle; _lengthDecrement = 1; // default handles bad parameters if (myLengthDecrement > 0){ _lengthDecrement = myLengthDecrement; } // draw method defined soon... } }

More Related