softwaredesignpattern
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
softwaredesignpattern [2014/06/19 11:17] – [Design] admin | softwaredesignpattern [2022/10/29 16:15] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | Refer: http:// | ||
+ | ====== Software Design Pattern ====== | ||
+ | **Design patterns** represent the best practices **used by experienced object-oriented software developers**. Design patterns are **solutions to general problems that software developers faced during software development**. These solutions were obtained by trial and error by numerous software developers over quite a substantial period of time. | ||
+ | **Types of Desing Pattern**: | ||
+ | ^S.N.^Name^Pattern & Description^ | ||
+ | |1|**Creational Patterns**|These design patterns provides **way to create objects while hiding the creation logic**, rather than instantiating objects directly using new opreator. This gives program more flexibility in deciding which objects need to be created for a given use case.| | ||
+ | |2|**Structural Patterns**|These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and **define ways to compose objects to obtain new functionalities**.| | ||
+ | |3|**Behavioral Patterns**|These design patterns are specifically **concerned with communication between objects**.| | ||
+ | |4|**J2EE Patterns**|These design patterns are specifically **concerned with the presentation tier**. These patterns are identified by Sun Java Center.| | ||
+ | ===== Creational Pattern: Factory Pattern ===== | ||
+ | Factory pattern is one of most used design pattern in Java. This type of design pattern comes under creational pattern as **this pattern provides one of the best ways to create an object**. | ||
+ | ==== Design ==== | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create an interface **Shape.java**:< | ||
+ | public interface Shape { | ||
+ | void draw(); | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create **concrete classes** implementing the same interface. | ||
+ | * Rectangle.java< | ||
+ | public class Rectangle implements Shape { | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * Square.java< | ||
+ | public class Square implements Shape { | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * Circle.java< | ||
+ | public class Circle implements Shape { | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create a Factory to generate object of concrete class based on given information **ShapeFactory.java**< | ||
+ | public class ShapeFactory { | ||
+ | |||
+ | //use getShape method to get object of type shape | ||
+ | | ||
+ | if(shapeType == null){ | ||
+ | | ||
+ | } | ||
+ | if(shapeType.equalsIgnoreCase(" | ||
+ | | ||
+ | } else if(shapeType.equalsIgnoreCase(" | ||
+ | | ||
+ | } else if(shapeType.equalsIgnoreCase(" | ||
+ | | ||
+ | } | ||
+ | return null; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Use the Factory to get object of concrete class by passing an information such as type FactoryPatternDemo.java:< | ||
+ | public class FactoryPatternDemo { | ||
+ | |||
+ | | ||
+ | ShapeFactory shapeFactory = new ShapeFactory(); | ||
+ | |||
+ | //get an object of Circle and call its draw method. | ||
+ | Shape shape1 = shapeFactory.getShape(" | ||
+ | |||
+ | //call draw method of Circle | ||
+ | shape1.draw(); | ||
+ | |||
+ | //get an object of Rectangle and call its draw method. | ||
+ | Shape shape2 = shapeFactory.getShape(" | ||
+ | |||
+ | //call draw method of Rectangle | ||
+ | shape2.draw(); | ||
+ | |||
+ | //get an object of Square and call its draw method. | ||
+ | Shape shape3 = shapeFactory.getShape(" | ||
+ | |||
+ | //call draw method of circle | ||
+ | shape3.draw(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Verify the output.< | ||
+ | Inside Circle:: | ||
+ | Inside Rectangle:: | ||
+ | Inside Square:: | ||
+ | </ | ||
+ | ===== creational pattern: Singleton Pattern ===== | ||
+ | This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.Ensure a class has only one instance, and provide a global point of access to it | ||
+ | ==== Design ==== | ||
+ | We're going to **create a SingleObject class**. SingleObject class have its constructor as private and **have a static instance of itself**. | ||
+ | |||
+ | SingleObject class provides a static method to get its static instance to outside world. SingletonPatternDemo, | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create a Singleton Class SingleObject.java< | ||
+ | public class SingleObject { | ||
+ | |||
+ | // | ||
+ | | ||
+ | |||
+ | // | ||
+ | // | ||
+ | | ||
+ | |||
+ | //Get the only object available | ||
+ | | ||
+ | return instance; | ||
+ | } | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Get the only object from the singleton class SingletonPatternDemo.java< | ||
+ | public class SingletonPatternDemo { | ||
+ | | ||
+ | |||
+ | //illegal construct | ||
+ | //Compile Time Error: The constructor SingleObject() is not visible | ||
+ | // | ||
+ | |||
+ | //Get the only object available | ||
+ | SingleObject object = SingleObject.getInstance(); | ||
+ | |||
+ | //show the message | ||
+ | object.showMessage(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Verify the output< | ||
+ | Hello World! | ||
+ | </ | ||
+ | ===== Structural Pattern: Adapter Pattern ===== | ||
+ | Adapter pattern works as **a bridge between two incompatible interfaces**. This type of design pattern comes under structural pattern as this pattern combines the capability of two independent interfaces. | ||
+ | ==== Design ==== | ||
+ | We've an interface **MediaPlayer interface** and a concrete class AudioPlayer implementing the MediaPlayer interface. AudioPlayer can **play mp3 format** audio files by default. | ||
+ | |||
+ | We're having another interface **AdvancedMediaPlayer interface** and concrete classes implementing the AdvancedMediaPlayer interface.These classes can **play vlc and mp4 format** files. | ||
+ | |||
+ | We want to **make AudioPlayer to play other formats as well**. To attain this, we've **created an adapter class MediaAdapter** which implements the MediaPlayer interface and uses AdvancedMediaPlayer objects to play the required format.\\ | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: **Create interfaces** for Media Player and Advanced Media Player | ||
+ | * MediaPlayer.java< | ||
+ | public interface MediaPlayer { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | * AdvancedMediaPlayer.java< | ||
+ | public interface AdvancedMediaPlayer { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create **concrete classes** implementing the AdvancedMediaPlayer interface | ||
+ | * VlcPlayer.java< | ||
+ | public class VlcPlayer implements AdvancedMediaPlayer{ | ||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | //do nothing | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * Mp4Player.java< | ||
+ | public class Mp4Player implements AdvancedMediaPlayer{ | ||
+ | |||
+ | | ||
+ | | ||
+ | //do nothing | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create **adapter class** implementing the MediaPlayer interface MediaAdapter.java< | ||
+ | public class MediaAdapter implements MediaPlayer { | ||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | if(audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | } else if (audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | if(audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | }else if(audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Create **concrete class implementing the MediaPlayer interface** AudioPlayer.java< | ||
+ | public class AudioPlayer implements MediaPlayer { | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | //inbuilt support to play mp3 music files | ||
+ | if(audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | } | ||
+ | // | ||
+ | else if(audioType.equalsIgnoreCase(" | ||
+ | || audioType.equalsIgnoreCase(" | ||
+ | | ||
+ | | ||
+ | } | ||
+ | else{ | ||
+ | | ||
+ | audioType + " format not supported" | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Use the AudioPlayer to **play different types of audio formats** AdapterPatternDemo.java< | ||
+ | public class AdapterPatternDemo { | ||
+ | | ||
+ | AudioPlayer audioPlayer = new AudioPlayer(); | ||
+ | |||
+ | audioPlayer.play(" | ||
+ | audioPlayer.play(" | ||
+ | audioPlayer.play(" | ||
+ | audioPlayer.play(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 6: Verify the output< | ||
+ | Playing mp3 file. Name: beyond the horizon.mp3 | ||
+ | Playing mp4 file. Name: alone.mp4 | ||
+ | Playing vlc file. Name: far far away.vlc | ||
+ | Invalid media. avi format not supported | ||
+ | </ | ||
+ | ===== Structural Pattern: Composite Pattern ===== | ||
+ | Composite pattern is used where we need to treat a group of objects in similar way as a single object. | ||
+ | ==== Design ==== | ||
+ | We've a **class Employee** which **acts as composite pattern actor class**. CompositePatternDemo, | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create Employee class having list of Employee objects Employee.java< | ||
+ | import java.util.ArrayList; | ||
+ | import java.util.List; | ||
+ | |||
+ | public class Employee { | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // constructor | ||
+ | | ||
+ | this.name = name; | ||
+ | this.dept = dept; | ||
+ | this.salary = sal; | ||
+ | subordinates = new ArrayList< | ||
+ | } | ||
+ | |||
+ | | ||
+ | subordinates.add(e); | ||
+ | } | ||
+ | |||
+ | | ||
+ | subordinates.remove(e); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | return (" | ||
+ | +", dept : "+ dept + ", salary :" | ||
+ | + salary+" | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Use the Employee class to create and print employee hierarchy CompositePatternDemo.java< | ||
+ | public class CompositePatternDemo { | ||
+ | | ||
+ | Employee CEO = new Employee(" | ||
+ | |||
+ | Employee headSales = new Employee(" | ||
+ | |||
+ | Employee headMarketing = new Employee(" | ||
+ | |||
+ | Employee clerk1 = new Employee(" | ||
+ | Employee clerk2 = new Employee(" | ||
+ | |||
+ | Employee salesExecutive1 = new Employee(" | ||
+ | Employee salesExecutive2 = new Employee(" | ||
+ | |||
+ | CEO.add(headSales); | ||
+ | CEO.add(headMarketing); | ||
+ | |||
+ | headSales.add(salesExecutive1); | ||
+ | headSales.add(salesExecutive2); | ||
+ | |||
+ | headMarketing.add(clerk1); | ||
+ | headMarketing.add(clerk2); | ||
+ | |||
+ | //print all employees of the organization | ||
+ | System.out.println(CEO); | ||
+ | for (Employee headEmployee : CEO.getSubordinates()) { | ||
+ | | ||
+ | for (Employee employee : headEmployee.getSubordinates()) { | ||
+ | System.out.println(employee); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Verify the output< | ||
+ | Employee :[ Name : John, dept : CEO, salary :30000 ] | ||
+ | Employee :[ Name : Robert, dept : Head Sales, salary :20000 ] | ||
+ | Employee :[ Name : Richard, dept : Sales, salary :10000 ] | ||
+ | Employee :[ Name : Rob, dept : Sales, salary :10000 ] | ||
+ | Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ] | ||
+ | Employee :[ Name : Laura, dept : Marketing, salary :10000 ] | ||
+ | Employee :[ Name : Bob, dept : Marketing, salary :10000 ] | ||
+ | </ | ||
+ | ===== Structural Pattern: Decorator pattern ===== | ||
+ | Decorator pattern allows to **add new functionality an existing object without altering its structure**. This type of design pattern comes under structural pattern as this pattern **acts as a wrapper to existing class**. | ||
+ | ==== Design ==== | ||
+ | Below are demonstrating use of Decorator pattern via following example in which we'll **decorate a shape** with **some color without alter shape class**. | ||
+ | |||
+ | We're going to create a **Shape interface** and concrete classes implementing the Shape interface. We then create a abstract decorator **class ShapeDecorator implementing the Shape interface** and having Shape object as its instance variable. | ||
+ | |||
+ | **RedShapeDecorator** is concrete class **implementing ShapeDecorator**. | ||
+ | |||
+ | DecoratorPatternDemo, | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create an **interface Shape.java**< | ||
+ | public interface Shape { | ||
+ | void draw(); | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create concrete classes implementing the same interface: | ||
+ | * Rectangle.java< | ||
+ | public class Rectangle implements Shape { | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * Circle.java< | ||
+ | public class Circle implements Shape { | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create **abstract decorator class** implementing the Shape interface **ShapeDecorator.java**< | ||
+ | public abstract class ShapeDecorator implements Shape { | ||
+ | | ||
+ | |||
+ | | ||
+ | this.decoratedShape = decoratedShape; | ||
+ | } | ||
+ | |||
+ | | ||
+ | decoratedShape.draw(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Create concrete decorator class **extending the ShapeDecorator class RedShapeDecorator.java**< | ||
+ | public class RedShapeDecorator extends ShapeDecorator { | ||
+ | |||
+ | | ||
+ | super(decoratedShape); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | decoratedShape.draw(); | ||
+ | setRedBorder(decoratedShape); | ||
+ | } | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Use the **RedShapeDecorator** to **decorate Shape objects** DecoratorPatternDemo.java< | ||
+ | public class DecoratorPatternDemo { | ||
+ | | ||
+ | |||
+ | Shape circle = new Circle(); | ||
+ | |||
+ | Shape redCircle = new RedShapeDecorator(new Circle()); | ||
+ | |||
+ | Shape redRectangle = new RedShapeDecorator(new Rectangle()); | ||
+ | System.out.println(" | ||
+ | circle.draw(); | ||
+ | |||
+ | System.out.println(" | ||
+ | redCircle.draw(); | ||
+ | |||
+ | System.out.println(" | ||
+ | redRectangle.draw(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 6: Verify the output< | ||
+ | Circle with normal border | ||
+ | Shape: Circle | ||
+ | |||
+ | Circle of red border | ||
+ | Shape: Circle | ||
+ | Border Color: Red | ||
+ | |||
+ | Rectangle of red border | ||
+ | Shape: Rectangle | ||
+ | Border Color: Red | ||
+ | </ | ||
+ | ===== Behavior Pattern: Iterator Pattern ===== | ||
+ | Iterator pattern is very commonly used design pattern in Java and .Net programming environment. This pattern is used to **get a way to access the elements of a collection object** in sequential manner **without any need to know its underlying representation**. | ||
+ | ==== Design ==== | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create interfaces: | ||
+ | * Iterator.java< | ||
+ | public interface Iterator { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | * Container.java< | ||
+ | public interface Container { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create concrete class implementing the Container interface. This class has inner class NameIterator implementing the Iterator interface NameRepository.java< | ||
+ | public class NameRepository implements Container { | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | return new NameIterator(); | ||
+ | } | ||
+ | |||
+ | | ||
+ | |||
+ | int index; | ||
+ | |||
+ | @Override | ||
+ | public boolean hasNext() { | ||
+ | | ||
+ | return true; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public Object next() { | ||
+ | | ||
+ | return names[index++]; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Use the NameRepository to get iterator and print names IteratorPatternDemo.java< | ||
+ | public class IteratorPatternDemo { | ||
+ | |||
+ | | ||
+ | NameRepository namesRepository = new NameRepository(); | ||
+ | |||
+ | for(Iterator iter = namesRepository.getIterator(); | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Verify the output< | ||
+ | Name : Robert | ||
+ | Name : John | ||
+ | Name : Julie | ||
+ | Name : Lora | ||
+ | </ | ||
+ | ===== Behavior Pattern: Observer Pattern ===== | ||
+ | Observer pattern is used when there is one to many relationship between objects such as **if one object is modified, its depenedent objects are to be notified automatically**. Observer pattern falls under behavioral pattern category. | ||
+ | ==== Design ==== | ||
+ | Observer pattern uses three actor classes. **Subject, Observer and Client**. **Subject, an object having methods to attach and de-attach observers to a client object**. We've created classes Subject, Observer abstract class and concrete classes extending the abstract class the Observer. | ||
+ | |||
+ | ObserverPatternDemo, | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create **Subject class** Subject.java:< | ||
+ | import java.util.ArrayList; | ||
+ | import java.util.List; | ||
+ | |||
+ | public class Subject { | ||
+ | |||
+ | | ||
+ | = new ArrayList< | ||
+ | | ||
+ | |||
+ | | ||
+ | return state; | ||
+ | } | ||
+ | |||
+ | | ||
+ | this.state = state; | ||
+ | notifyAllObservers(); | ||
+ | } | ||
+ | |||
+ | | ||
+ | observers.add(observer); | ||
+ | } | ||
+ | |||
+ | | ||
+ | for (Observer observer : observers) { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create Observer class Observer.java< | ||
+ | public abstract class Observer { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create concrete observer classes: | ||
+ | * BinaryObserver.java< | ||
+ | public class BinaryObserver extends Observer{ | ||
+ | |||
+ | | ||
+ | this.subject = subject; | ||
+ | this.subject.attach(this); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println( " | ||
+ | + Integer.toBinaryString( subject.getState() ) ); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * OctalObserver.java< | ||
+ | public class OctalObserver extends Observer{ | ||
+ | |||
+ | | ||
+ | this.subject = subject; | ||
+ | this.subject.attach(this); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | + Integer.toOctalString( subject.getState() ) ); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * HexaObserver.java< | ||
+ | public class HexaObserver extends Observer{ | ||
+ | |||
+ | | ||
+ | this.subject = subject; | ||
+ | this.subject.attach(this); | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | System.out.println( "Hex String: " | ||
+ | + Integer.toHexString( subject.getState() ).toUpperCase() ); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Use Subject and concrete observer objects ObserverPatternDemo.java< | ||
+ | public class ObserverPatternDemo { | ||
+ | | ||
+ | Subject subject = new Subject(); | ||
+ | |||
+ | new HexaObserver(subject); | ||
+ | new OctalObserver(subject); | ||
+ | new BinaryObserver(subject); | ||
+ | |||
+ | System.out.println(" | ||
+ | subject.setState(15); | ||
+ | System.out.println(" | ||
+ | subject.setState(10); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Verify the output< | ||
+ | First state change: 15 | ||
+ | Hex String: F | ||
+ | Octal String: 17 | ||
+ | Binary String: 1111 | ||
+ | Second state change: 10 | ||
+ | Hex String: A | ||
+ | Octal String: 12 | ||
+ | Binary String: 1010 | ||
+ | </ | ||
+ | ===== Behavior Pattern: | ||
+ | In State pattern a **class behavior changes based on its state**. This type of design pattern comes under behavior pattern. | ||
+ | ==== Design ==== | ||
+ | We're going to create a **State interface defining a action** and **concrete state classes implementing the State interface**. Context is a class which carries a State. | ||
+ | |||
+ | StatePatternDemo, | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create an interface Image.java< | ||
+ | public interface State { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create concrete classes implementing the same interface | ||
+ | * StartState.java< | ||
+ | public class StartState implements State { | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | context.setState(this); | ||
+ | } | ||
+ | |||
+ | | ||
+ | return "Start State"; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * StopState.java< | ||
+ | public class StopState implements State { | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | context.setState(this); | ||
+ | } | ||
+ | |||
+ | | ||
+ | return "Stop State"; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create Context Class Context.java< | ||
+ | public class Context { | ||
+ | | ||
+ | |||
+ | | ||
+ | state = null; | ||
+ | } | ||
+ | |||
+ | | ||
+ | this.state = state; | ||
+ | } | ||
+ | |||
+ | | ||
+ | return state; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Use the Context to see change in behaviour when State changes StatePatternDemo.java< | ||
+ | public class StatePatternDemo { | ||
+ | | ||
+ | Context context = new Context(); | ||
+ | |||
+ | StartState startState = new StartState(); | ||
+ | startState.doAction(context); | ||
+ | |||
+ | System.out.println(context.getState().toString()); | ||
+ | |||
+ | StopState stopState = new StopState(); | ||
+ | stopState.doAction(context); | ||
+ | |||
+ | System.out.println(context.getState().toString()); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Verify the output< | ||
+ | Player is in start state | ||
+ | Start State | ||
+ | Player is in stop state | ||
+ | Stop State | ||
+ | </ | ||
+ | ===== Model-View-Controller Pattern ===== | ||
+ | This pattern is used to separate application' | ||
+ | * Model - Model **represents an object** or JAVA POJO carrying data. It can **also have logic to update controller if its data changes**. | ||
+ | * View - View **represents the visualization of the data** that model contains. | ||
+ | * Controller - Controller acts on both Model and view. It **controls the data flow into model object** and **updates the view whenever data changes**. It keeps **View and Model separate**. | ||
+ | ==== Design ==== | ||
+ | We're going to create a **Student object** acting as a model. **StudentView** will be a view class which can print student details on console and **StudentController** is the controller class responsible to store data in Student object and update view StudentView accordingly. | ||
+ | |||
+ | **MVCPatternDemo**, | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create Model Student.java< | ||
+ | public class Student { | ||
+ | | ||
+ | | ||
+ | | ||
+ | return rollNo; | ||
+ | } | ||
+ | | ||
+ | this.rollNo = rollNo; | ||
+ | } | ||
+ | | ||
+ | return name; | ||
+ | } | ||
+ | | ||
+ | this.name = name; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create View StudentView.java< | ||
+ | public class StudentView { | ||
+ | | ||
+ | System.out.println(" | ||
+ | System.out.println(" | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create Controller StudentController.java< | ||
+ | public class StudentController { | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | this.model = model; | ||
+ | this.view = view; | ||
+ | } | ||
+ | |||
+ | | ||
+ | model.setName(name); | ||
+ | } | ||
+ | |||
+ | | ||
+ | return model.getName(); | ||
+ | } | ||
+ | |||
+ | | ||
+ | model.setRollNo(rollNo); | ||
+ | } | ||
+ | |||
+ | | ||
+ | return model.getRollNo(); | ||
+ | } | ||
+ | |||
+ | | ||
+ | view.printStudentDetails(model.getName(), | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Use the StudentController methods to demonstrate MVC design pattern usage MVCPatternDemo.java< | ||
+ | public class MVCPatternDemo { | ||
+ | | ||
+ | |||
+ | //fetch student record based on his roll no from the database | ||
+ | Student model = retriveStudentFromDatabase(); | ||
+ | |||
+ | //Create a view : to write student details on console | ||
+ | StudentView view = new StudentView(); | ||
+ | |||
+ | StudentController controller = new StudentController(model, | ||
+ | |||
+ | controller.updateView(); | ||
+ | |||
+ | //update model data | ||
+ | controller.setStudentName(" | ||
+ | |||
+ | controller.updateView(); | ||
+ | } | ||
+ | |||
+ | | ||
+ | Student student = new Student(); | ||
+ | student.setName(" | ||
+ | student.setRollNo(" | ||
+ | return student; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Verify the output< | ||
+ | Student: | ||
+ | Name: Robert | ||
+ | Roll No: 10 | ||
+ | Student: | ||
+ | Name: John | ||
+ | Roll No: 10 | ||
+ | </ | ||
+ | ===== Behavior Pattern: | ||
+ | ==== Design ==== | ||
+ | We've created an **interface Order** which is **acting as a command**. We've created a **Stock class** which acts **as a request**. We've concrete command classes **BuyStock and SellStock implementing Order interface** which will do **actual command processing**. A class **Broker** is created which acts **as a invoker object**. It can take order and place orders. | ||
+ | |||
+ | Broker object uses command pattern to identify which object will execute which command based on type of command. CommandPatternDemo, | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create a command interface Order.java< | ||
+ | public interface Order { | ||
+ | void execute(); | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create a request class Stock.java< | ||
+ | public class Stock { | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | | ||
+ | } | ||
+ | | ||
+ | System.out.println(" | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Create concrete classes implementing the Order interface: | ||
+ | * BuyStock.java< | ||
+ | public class BuyStock implements Order { | ||
+ | | ||
+ | |||
+ | | ||
+ | this.abcStock = abcStock; | ||
+ | } | ||
+ | |||
+ | | ||
+ | abcStock.buy(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | * SellStock.java< | ||
+ | public class SellStock implements Order { | ||
+ | | ||
+ | |||
+ | | ||
+ | this.abcStock = abcStock; | ||
+ | } | ||
+ | |||
+ | | ||
+ | abcStock.sell(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Create command invoker class Broker.java< | ||
+ | import java.util.ArrayList; | ||
+ | import java.util.List; | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | orderList.add(order); | ||
+ | } | ||
+ | |||
+ | | ||
+ | for (Order order : orderList) { | ||
+ | | ||
+ | } | ||
+ | orderList.clear(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 5: Use the Broker class to take and execute commands CommandPatternDemo.java< | ||
+ | public class CommandPatternDemo { | ||
+ | | ||
+ | Stock abcStock = new Stock(); | ||
+ | |||
+ | BuyStock buyStockOrder = new BuyStock(abcStock); | ||
+ | SellStock sellStockOrder = new SellStock(abcStock); | ||
+ | |||
+ | Broker broker = new Broker(); | ||
+ | broker.takeOrder(buyStockOrder); | ||
+ | broker.takeOrder(sellStockOrder); | ||
+ | |||
+ | broker.placeOrders(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 6: Verify the output< | ||
+ | Stock [ Name: ABC, Quantity: 10 ] bought | ||
+ | Stock [ Name: ABC, Quantity: 10 ] sold | ||
+ | </ | ||
+ | ===== Behavior Pattern: Template Pattern ===== | ||
+ | Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm' | ||
+ | ==== Design ==== | ||
+ | {{: | ||
+ | {{: | ||
+ | ==== Implementation ==== | ||
+ | - Step 1: Create an abstract class with a template method being final Game.java< | ||
+ | public abstract class Game { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // | ||
+ | | ||
+ | |||
+ | // | ||
+ | initialize(); | ||
+ | |||
+ | //start game | ||
+ | startPlay(); | ||
+ | |||
+ | //end game | ||
+ | endPlay(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 2: Create concrete classes extending the above class | ||
+ | * Cricket.java< | ||
+ | public class Cricket extends Game { | ||
+ | |||
+ | | ||
+ | void endPlay() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | void initialize() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | void startPlay() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | * Football.java< | ||
+ | public class Football extends Game { | ||
+ | |||
+ | | ||
+ | void endPlay() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | void initialize() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | void startPlay() { | ||
+ | System.out.println(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 3: Use the Game's template method play() to demonstrate a defined way of playing game TemplatePatternDemo.java< | ||
+ | public class TemplatePatternDemo { | ||
+ | | ||
+ | |||
+ | Game game = new Cricket(); | ||
+ | game.play(); | ||
+ | System.out.println(); | ||
+ | game = new Football(); | ||
+ | game.play(); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | - Step 4: Verify the output< | ||
+ | Cricket Game Initialized! Start playing. | ||
+ | Cricket Game Started. Enjoy the game! | ||
+ | Cricket Game Finished! | ||
+ | |||
+ | Football Game Initialized! Start playing. | ||
+ | Football Game Started. Enjoy the game! | ||
+ | Football Game Finished! | ||
+ | </ |