Design patterns
Design patterns are programming language independent strategies for solving the common object-oriented design problems. That means, a design pattern represents an idea, not a particular implementation. By using the design patterns you can make your code more flexible, reusable and maintainable. It is the most important part because java internally follows design patterns.
Advantage of design pattern:
- They are reusable in multiple projects.
- They provide the solutions that help to define the system architecture.
- They capture the software engineering experiences.
- They provide transparency to the design of an application.
- They are well-proved and testified solutions since they have been built upon the knowledge and experience of expert software developers.
Design patterns don't guarantee an absolute solution to a problem. They provide clarity to the system architecture and the possibility of building a better system.
When should we use the design patterns
We must use the design patterns during the analysis and design requirement phase of SDLC(Software Development Life Cycle).
Design patterns ease the analysis and requirement phase of SDLC by providing information based on prior hands-on experiences.
1.Creational Design Pattern - provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case.
- Factory Pattern
- Abstract Factory Pattern
- Singleton Pattern
- Prototype Pattern
- Builder Pattern.
2. Structural Design Pattern -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.
- Adapter Pattern
- Bridge Pattern
- Composite Pattern
- Decorator Pattern
- Facade Pattern
- Flyweight Pattern
- Proxy Pattern
3. Behavioral Design Pattern - These design patterns are specifically concerned with communication between objects.
- Chain Of Responsibility Pattern
- Command Pattern
- Interpreter Pattern
- Iterator Pattern
- Mediator Pattern
- Memento Pattern
- Observer Pattern
- State Pattern
- Strategy Pattern
- Template Pattern
- Visitor Pattern
- When a class doesn't know what sub-classes will be required to create
- When a class wants that its sub-classes specify the objects to be created.
- When the parent classes choose the creation of objects to its sub-classes.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class FactoryPattern {
public static void main(String args[]) throws IOException {
GetRoomFactory roomFactory = new GetRoomFactory();
System.out.print("Enter the name of room for which the bill will be generated: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String roomName = br.readLine();
System.out.print("Enter the number of people for bill will be calculated: ");
int opeople = Integer.parseInt(br.readLine());
Room p = roomFactory.getRoom(roomName);
System.out.print("Bill amount for " + roomName + " of " + opeople + " people is: ");
p.getRate();
p.calculateBill(opeople);
}
}
abstract class Room {
protected double rate;
abstract void getRate();
public void calculateBill(int people) {
System.out.println(people * rate);
}
}
class Luxury extends Room {
//@override
public void getRate() {
rate = 13.50;
}
}
class Normal extends Room {
//@override
public void getRate() {
rate = 7.50;
}
}
class GetRoomFactory {
//use getPlan method to get object of type Plan
public Room getRoom(String roomType) {
if (roomType == null) {
return null;
}
if (roomType.equalsIgnoreCase("Luxury")) {
return new Luxury();
} else if (roomType.equalsIgnoreCase("Normal")) {
return new Normal();
}
return null;
}
}
- static member of class,
- private constructor
- static factory method.
public class SingletonPrinter {
private static SingletonPrinter printer =new SingletonPrinter();//Early, instance will be created at load time
private SingletonPrinter(){}
public static SingletonPrinter getPrinter(){
return printer;
}
public static void main(String args[]){
getPrinter().hashCode();
}
}
- Create a concrete builder class for each of the product representations and implement their construction steps.
- Don’t forget about implementing a method for fetching the result of the construction. The reason why this method can’t be declared inside the builder interface is that various builders may construct products that don’t have a common interface. Therefore, you don’t know what would be the return type for such a method. However, if you’re dealing with products from a single hierarchy, the fetching method can be safely added to the base interface.
- Think about creating a Builder class. It may encapsulate various ways to construct a product using the same builder object.
- The client code creates both the builder and the director objects. Before construction starts, the client must pass a builder object to the director. Usually, the client does this only once, via parameters of the director’s class constructor. The director uses the builder object in all further construction. There’s an alternative approach, where the builder is passed to a specific product construction method of the director.
- The construction result can be obtained directly from the director only if all products follow the same interface. Otherwise, the client should fetch the result from the builder.
class Profile{
}
interface ProfilesBuilder {
void setName();
void addMaterial();
void addVersion();
void addSettings();
void reSet();
}
class Builder implements ProfilesBuilder{
Profile profile;
Builder(){
reSet();
}
@Override
public void setName() {
}
@Override
public void addMaterial() {
}
@Override
public void addVersion() {
}
@Override
public void addSettings() {
}
@Override
public void reSet() {
this.profile = new Profile();
}
public Profile getProfile(){
profile = this.profile;
this.reSet();
return profile;
}
}
class Director {
private ProfilesBuilder builder;
void setBuilder(ProfilesBuilder builder){
this.builder = builder;
}
void makeSurgeonProfile(ProfilesBuilder surgeonProfile){
surgeonProfile.addMaterial();
surgeonProfile.addSettings();
surgeonProfile.addVersion();
}
void makeAnestheticProfile(ProfilesBuilder surgeonProfile){
surgeonProfile.addMaterial();
surgeonProfile.addSettings();
surgeonProfile.addVersion();
}
void makeSurgicleProfile(ProfilesBuilder surgeonProfile){
surgeonProfile.addMaterial();
surgeonProfile.addSettings();
surgeonProfile.addVersion();
}
}
public class BuilderDesignPattern {
public static void main(String args[]){
Director director = new Director();
Builder builder = new Builder();
director.makeSurgeonProfile(builder);
Profile surgeonProfile = builder.getProfile();
}
}
- It allows two or more previously incompatible objects to interact.
- It allows reusability of existing functionality
public class AdapterDesignPattern {
public static void main(String args[]) {
testAdapter();
}
private static void testAdapter() {
Amplifier speaker = new Speaker();
System.out.println(getDesible(speaker, 3).getDesible());
}
private static Desible getDesible(Amplifier speaker, int i) {
switch (i) {
case 2:
return speaker.getVolume2();
case 3:
return speaker.getVolume3();
}
return new Desible(0);
}
}
//To measure sound
class Desible {
public Desible(int desible) {
this.desible = desible;
}
public int getDesible() {
return desible;
}
public void setDesible(int desible) {
this.desible = desible;
}
int desible;
}
class Mike {
public Desible getDesible() {
return new Desible(1000);
}
}
//Adapter class
interface Amplifier {
Desible getVolume1();
Desible getVolume2();
Desible getVolume3();
}
class Speaker extends Mike implements Amplifier {
@Override
public Desible getVolume1() {
return getDesible();
}
@Override
public Desible getVolume2() {
return convertTODesible(getDesible(), 2);
}
@Override
public Desible getVolume3() {
return convertTODesible(getDesible(), 3);
}
private Desible convertTODesible(Desible d, int i) {
return new Desible(d.getDesible() * i);
}
}
public class DecoratorPattern {
public static void main(String args[]) {
Cake birthDayCake = new BirthDayCake();
System.out.println(birthDayCake.addDeco());
Cake icingBirthdayCake = new IcingDecorator(new BirthDayCake());
System.out.println(icingBirthdayCake.addDeco());
Cake anniversaryCakeWithStand = new CakeStandDecorator(new AnniversaryCake());
System.out.println(anniversaryCakeWithStand.addDeco());
}
}
interface Cake {
void makeMixture();
void bake();
String addDeco();
}
class BirthDayCake implements Cake {
@Override
public void makeMixture() {
}
@Override
public void bake() {
}
@Override
public String addDeco() {
return " Happy Birthday";
}
}
class AnniversaryCake implements Cake {
@Override
public void makeMixture() {
}
@Override
public void bake() {
}
@Override
public String addDeco() {
return " HAppy Anniversary";
}
}
abstract class CakeDecorator implements Cake {
protected Cake cakeDecorator;
public CakeDecorator(Cake decoratorCake) {
this.cakeDecorator = decoratorCake;
}
public String addDeco() {
return cakeDecorator.addDeco();
}
}
class IcingDecorator extends CakeDecorator {
public IcingDecorator(Cake decoratorCake) {
super(decoratorCake);
}
@Override
public void makeMixture() {
}
@Override
public void bake() {
}
@Override
public String addDeco() {
return super.addDeco() + " with icing Roses";
}
}
class CakeStandDecorator extends CakeDecorator {
public CakeStandDecorator(Cake decoratorCake) {
super(decoratorCake);
}
@Override
public void makeMixture() {
}
@Override
public void bake() {
}
@Override
public String addDeco() {
return super.addDeco() + " with wooden stand ";
}
}
import java.util.ArrayList;
import java.util.List;
class OperationCenter {
private List<Observer> observers = new ArrayList<Observer>();
private int roomID;
public int getRoomID() {
return roomID;
}
public void setRoomID(int roomID) {
this.roomID = roomID;
notifyAllObservers(roomID);
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(int roomID){
for (Observer observer : observers) {
observer.update(roomID);
}
}
}
abstract class Observer {
protected OperationCenter observerble;
public abstract void update(int room);
}
class operationOverview extends Observer{
public operationOverview(OperationCenter subject){
this.observerble = subject;
this.observerble.attach(this);
}
@Override
public void update(int room) {
System.out.println( "Update operation overview screen with new room ID " + room );
}
}
class operationMonitoring extends Observer{
public operationMonitoring(OperationCenter opCenter){
this.observerble = opCenter;
this.observerble.attach(this);
}
@Override
public void update(int room) {
System.out.println( "Update operation monitoring screen with room " + room);
}
}
public class ObserverDesignPattern {
public static void main(String args[]){
OperationCenter OperationCenter = new OperationCenter();
new operationOverview(OperationCenter);
new operationMonitoring(OperationCenter);
OperationCenter.setRoomID(15);
OperationCenter.setRoomID(7);
}
}
public class StratergyPattern {
public static void main(String args[]) {
context context = new context(new OptimalPlanningOperation());
context context1 = new context(new NormalPlanningOperation());
context.doPlanOperation();
context1.doPlanOperation();
}
}
class context{
private Stratergy stratergy;
public context(Stratergy stratergy){
this.stratergy = stratergy;
}
public boolean doPlanOperation(){
return stratergy.doPlanOperation();
}
}
interface Stratergy {
boolean doPlanOperation();
}
class OptimalPlanningOperation implements Stratergy {
@Override
public boolean doPlanOperation() {
System.out.println(" Do Optimal plan Logic...");
return true;
}
}
class NormalPlanningOperation implements Stratergy {
@Override
public boolean doPlanOperation() {
System.out.println(" Do Normal plan Logic...");
return true;
}
}
Comments
Post a Comment