Software Design and Patterns (Object Oriented Design)— Catalog of 23 GOF Design Patterns
Object Oriented Design (OOD)
Identify domain classes/objects — Real-world objects or concepts in the application, bridge the gap between high-level requirements and design. Design patterns provide a shared vocabulary to solve common problems. Frameworks make use of design patterns in their implementation.
The Gang of Four (GoF)
Summarize Object-Oriented Design in OOP — 23 Software Design Patterns Each in One Sentence, and how I see them applicable to a software application — The Gang of Four (GoF)
Why design patterns are even needed? The purpose of the design patterns is to reuse solutions that have been successful in the past to solve specific design problems and make object-oriented designs more flexible, reusable, and scalable as the software becomes more and more complex.
There are three types of design patterns - creational, structural, and behavioral:
Check details for each pattern in the Design Pattern Card.
Creational (the process of object creation)
- Abstract Factory: all the objects need to be created from this family
- Builder: sequence of steps are same but you build differently
- Factory Method: object let subclass decide which class to instantiate
- Prototype: clone the object instead of creating a new one
- Singleton: one class only one instance, a global point of access to it
Structural (ways components interact with each other)
- Adapter: convert an interface of a class to another to work together
- Bridge: change interface/abstract without implementation or vice versa
- Composition: same interface depends on hierarchy like tree structure
- Decorator: attach additional responsibilities on existing objects
- Facade: simple interface but complex logic behind the scene
- Flyweight: reduce memory usage by sharing data across large objects
- Proxy: provide a placeholder for another object to control access to it
Behavioral (ways to communicate between entities)
- Chain of Responsibility: delegate works to the lower chain until handled
- Command: execute operations with different requests, support un/redo
- Interpreter: to follow the sequence like a grammar to follow for a syntax
- Iterator: go through a list of interfaces do something regardless objects
- Mediator: for complex relationship go mediator instead of class directly
- Memento: remember if need to restore back later, keep track all capture
- Observer: one to many, one change, all dependencies notified/updated
- State: implementation of the method varies based on state of the object
- Strategy: implementation varies, switch from one another based on context
- Template Method: skeleton in operation then redefine code as abstract
- Visitor: add new operations without touching the class, not common
Considering the above GOF patterns, I would like to share how I see them applicable to a software application, I am going to use a telehealth software application as an example to briefly the context and how the pattern will help.
Regarding the creational software design pattern, the telehealth application itself would use a Singleton pattern where only one instance of the medical system should exist to maintain consistency for the purpose of consistency of data, centralization of access, and the efficient use of the resources and data its users rely on, e.g. the EMR system in healthcare for Electronic Medical Records.
To further examine the application, I would use Factory Pattern to create a virtual consultation with a medical provider that is requested by the user as a specific example. I am choosing this design pattern because it allows us to create instances of different subclasses using the same base class by conditional logic check. For instance, some users would need mental health consultation, some would need general care consultation, some would need pediatric consultation, some would need dermatology consultation, and so on. In this case, we can create a consultation as a superclass but with the flexibility to decide which object to return based on the data provided when creating subclasses in order to meet the needs of the end user.
public class ConsultationFactory {
public Consultation createConsultation(String type) {
Consultation consultation = null;
if (type.equals("mentalHealth")) {
consultation = new MentalHealthConsultation();
} else if (type.equals("generalCare")) {
consultation = new GeneralCareConsultation();
} else if (type.equals("pediatric")) {
consultation = new PediatricConsultation();
} else if (type.equals("dermatology")) {
consultation = new DermatologyConsultation();
}
return consultation;
}
}
Moreover, there are users who would prefer live video consultation, some would prefer telephone audio consultation, and some would prefer live chatting consultation. We can also use this design pattern to further expand our subclasses based on the preference of the end user.
Regarding the structural software design pattern, the application would use a façade pattern, for instance, when the user clicks a button to create a consultation, with a simple UI design as a button, there is complex logic behind the scene like provider matching, scheduling, etc. The proxy pattern would also be needed to control access to certain flows based on gender, payment, insurance coverage, etc. The Bridge pattern will work as the abstract class that has the concrete class to extend from, such as a consultation abstract class with scheduleAConsultation abstract method, then the concrete classes can extend from it and continue to implement it based on needs. The Flyweight pattern would be used to share data across a large number of objects such as the medical history of the patient across doctors and nurses and admin users and patient itself. The composition pattern would be used to represent the user interface of the software based on a tree hierarchy, such as a primary account holder with dependents under him/her but within the same insurance payment group. The decorator pattern would be used to add new functionalities to the user interface like additional inputs would be needed based on the assessment. The adapter pattern would be used to convert an interface of a class to another to work together; for example, if a special branch would like to use the service the telehealth company provides, then they can create an adapter to adapt between the telehealth service and the user interface for this special brand.
Regarding the behavioral software design pattern, the application would use a command pattern would be used to support undo and redo operations, such as cancellation and rescheduling a consultation. The iterator pattern would be used to go through the database to check the availability and specialty of the medical provider for the consultation. The memento pattern would be used to remember the user’s preference for consultation, such as the method of communication and the choice of the provider. The visitor pattern would be used to add new operations without adding to the consultation object based on the users’ needs and requests during consultation. The observer pattern would be used to notify either provider or the user regarding any update. The state pattern would be used to check if any follow-up visit would be needed based on the current state. The strategy pattern would be used to allow implementations to vary, and switch from one another based on context, such as can implement different consultation algorithms based on the communication preference of a user, then implementing the method of video or call or chat. The mediator pattern would be useful for complex relationships to go mediator instead of the class directly; such as a user would like to choose a medical provider based on preferred specialties, race/gender, insurance group, location, time schedule, etc.
The above analysis is how I see these design patterns applicable to a telehealth software application as a learning practice. An application could use multiple patterns among the list of patterns. I am sure there would be more patterns being used and more complexity behind the design architecture.