When you land your first job as a junior developer your first code will look like a complex maze but with time you will learn many patterns that can be applied to your favorite programming language first let's get the definition of design patterns. Design Patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code. the Design Patterns can differ by their complexity, level of detail, and scale of applicability. In addition, they can be categorized by their intent and divided into three groups.
1. Creational Design Patterns
Creational design patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.
- Factory Method : is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. Make all products follow the same interface. This interface should declare methods that make sense in every product. the pros of this method are : you avoid tight coupling between the creator and the concrete products. Single Responsibility Principale You can move the product creation code into one place in the program, making the code easier to support. Open/Closed Principle, you can introduce new types of products into the program without breaking existing client code. the cons of the factory method are only the code becomes more complicated since you need to introduce a lot of new subclasses to implement the pattern. the best-case scenario is when you're introducing the pattern into an existing hierarchy of creator classes.
-The builder method : is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code. the pros of it : You can construct objects step-by-step, defer construction steps or run steps recursively. You can reuse the same construction code when building various representations of products. Single Responsibility Principle. You can isolate complex construction code from the business logic of the product. And cons is The overall complexity of the code increases since the pattern requires creating multiple new classes.
-Prototype : is a creational design pattern that lets you copy existing objects without making your code dependent on their classes. this method is good when You can clone objects without coupling to their concrete classes. You can get rid of repeated initialization code in favor of cloning pre-built prototypes. You can produce complex objects more conveniently. You get an alternative to inheritance when dealing with configuration presets for complex objects. and it is bad when you cloned complex objects that have circular references might be very tricky.
- Singleton is a creational design pattern that lets you ensure that a class has only one instance while providing a global access point to this instance. the singleton method is famous among other design pattern architects and it is good when You can be sure that a class has only a single instance. You gain a global access point to that instance. The singleton object is initialized only when it’s requested for the first time. although it has many bad things like violating the Single Responsibility Principle. The pattern solves two problems at the time. The Singleton pattern can mask bad design, for instance, when the components of the program know too much about each other. The pattern requires special treatment in a multithreaded environment so that multiple threads won’t create a singleton object several times. It may be difficult to unit test the client code of the Singleton because many test frameworks rely on inheritance when producing mock objects. Since the constructor of the singleton class is private and overriding static methods is impossible in most languages, you will need to think of a creative way to mock the singleton. Or just don’t write the tests. Or don’t use the Singleton pattern.
2. Structural Design Patterns
Structural design patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient. it has many patterns but I will explain just Two the Facade and Proxy.
-Facade: is a structural design pattern that provides a simplified interface to a library, a framework, or any other complex set of classes. this pattern can isolate your code from the complexity of subsystem but can become a god object coupled to all classes of an app.
-Proxy : is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object. the good thing about this pattern is You can control the service object without clients knowing about it. You can manage the lifecycle of the service object when clients don’t care about it. The proxy works even if the service object isn’t ready or is not available. Open/Closed Principle. You can introduce new proxies without changing the service or clients. but The code may become more complicated since you need to introduce a lot of new classes. The response from the service might get delayed.
3. Structural Design Patterns
Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.
-Iterator : is a behavioral design pattern that lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.). the pros of it are : Single Responsibility Principle. You can clean up the client code and the collections by extracting bulky traversal algorithms into separate classes. Open/Closed Principle. You can implement new types of collections and iterators and pass them to existing code without breaking anything. You can iterate over the same collection in parallel because each iterator object contains its own iteration state. For the same reason, you can delay an iteration and continue it when needed. but it also Applying the pattern can be an overkill if your app only works with simple collections. Using an iterator may be less efficient than going through elements of some specialized collections directly.
-Mediator is a behavioral design pattern that lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object. also, this pattern has the Single Responsibility Principle. You can extract the communications between various components into a single place, making it easier to comprehend and maintain. Open/Closed Principle. You can introduce new mediators without having to change the actual components. You can reduce coupling between various components of a program. You can reuse individual components more easily. but also Over time, a mediator can evolve into a God Object.
-Observer : is a behavioral design pattern that lets you define a subscription mechanism to notify multiple objects about any events that happen to the object they’re observing. its pros are the Open/Closed Principle. You can introduce new subscriber classes without having to change the publisher’s code (and vice versa if there’s a publisher interface). You can establish relations between objects at runtime. but Subscribers are notified in random order.
-State is a behavioral design pattern that lets an object alter its behavior when its internal state changes. It appears as if the object changed its class. its goods are the Single Responsibility Principle. Organize the code related to particular states into separate classes. Open/Closed Principle. Introduce new states without changing existing state classes or the context. Simplify the code of the context by eliminating bulky state machine conditionals. but also Applying the pattern can be overkill if a state machine has only a few states or rarely changes.
No matter which pattern you select to follow but just be sure that your choice will have a direct effect on the software development process because any wrong estimation or making a wrong concept building will make everything collapse badly.