Book Image

Hands-On Design Patterns with Delphi

By : Primož Gabrijelčič
Book Image

Hands-On Design Patterns with Delphi

By: Primož Gabrijelčič

Overview of this book

Design patterns have proven to be the go-to solution for many common programming scenarios. This book focuses on design patterns applied to the Delphi language. The book will provide you with insights into the language and its capabilities of a runtime library. You'll start by exploring a variety of design patterns and understanding them through real-world examples. This will entail a short explanation of the concept of design patterns and the original set of the 'Gang of Four' patterns, which will help you in structuring your designs efficiently. Next, you'll cover the most important 'anti-patterns' (essentially bad software development practices) to aid you in steering clear of problems during programming. You'll then learn about the eight most important patterns for each creational, structural, and behavioral type. After this, you'll be introduced to the concept of 'concurrency' patterns, which are design patterns specifically related to multithreading and parallel computation. These will enable you to develop and improve an interface between items and harmonize shared memories within threads. Toward the concluding chapters, you'll explore design patterns specific to program design and other categories of patterns that do not fall under the 'design' umbrella. By the end of this book, you'll be able to address common design problems encountered while developing applications and feel confident while building scalable projects.
Table of Contents (18 chapters)
Title Page
Copyright and Credits
About Packt
Contributors
Preface
Index

Pattern taxonomy


The original Gang of Four book separated patterns into three categories: creational, structural, and behavioral. To these three, another large category was added in recent years, concurrency patterns. Some concurrency patterns were covered in another classic book: Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects, Volume 2, by  Douglas C Schmidt, Michael Stal, Hans Rohnert, and Frank Buschmann.

Creational patterns deal with delegation. They are focused on creating new objects and groups of related objects. These patterns will create objects for you, meaning that you don't have to create them directly.

The focus of structural patterns is aggregation. They define ways to compose objects in a way that creates new functionality from the constituent parts. They help us create software components.

Behavioral patterns are big on consultation they talk about responsibilities between objects. Unlike structural patterns, which only specify a structure, behavioral patterns define communication paths and messages.

 

Concurrency patterns deal with cooperation. They make a system composed of multiple components, running in parallel, work together. The main concerns of concurrency patterns are resource protection and messaging.

The next few pages will give an overview of the most important design patterns, organized by category and sorted by name.

Creational patterns

The patterns in the first group of patterns, creational patterns, are used when simple and composite objects are created. The following patterns belong to this group:

  • Abstract factory pattern: You can use this pattern to create entire families of related objects but without the need to specify their classes. This pattern is described in Chapter 3, Factory Method, Abstract Factory, Prototype, and Builder.
  • Builder pattern: This pattern abstracts the construction of a complex object, and allows the same process to create different representations. It is described inChapter 2, Singleton, Dependency Injection, Lazy Initialization, and Object Pool.
  • Dependency injection pattern: This is used to send specific instances of depended objects into a class (injecting them), instead of the class creating them directly. This pattern is described inChapter 3, Factory Method, Abstract Factory, Prototype, and Builder.
  • Factory method pattern: This pattern defines an interface for creating a single object. Subclasses can then decide which class to instantiate. This is described inChapter 3, Factory Method, Abstract Factory, Prototype, and Builder.
  • Lazy initialization pattern: This delays the creation of an object or the calculation of a value until it is actually needed. In the GoF book, it appeared as a virtual proxy. This pattern is described inChapter 3, Factory Method, Abstract Factory, Prototype, and Builder.
  • Multiton pattern: This pattern similar to singleton. It allows multiple named instances, while serving as the only way of accessing them. It is not covered in this book.
  • Object pool pattern: This pattern recycles objects to avoid the expensive acquisition and creation of resources. A special case, connection pool, is well-known to all database programmers. This pattern is described inChapter 2, Singleton, Dependency Injection, Lazy Initialization, and Object Pool.
  • Prototype pattern: This specifies how to create objects based on a template object that is cloned to produce new objects. This pattern is described inChapter 2, Singleton, Dependency Injection, Lazy Initialization, and Object Pool.
  • Resource acquisition is initialization pattern (RAII): This pattern ensures that resources are properly released by tying them to the lifespan of an object. In Delphi, we implement this pattern by using an interface as a resource owner. It is not covered in this book.
  • Singleton pattern: This pattern ensures that a class has only one instance. It also provides a common point of access to that instance. This pattern is described inChapter 2, Singleton, Dependency Injection, Lazy Initialization, and Object Pool.

Structural patterns

The second group of patterns, structural patterns, handles the way objects are composed into new objects. The following patterns belong to this group:

  • Adapter pattern: This pattern, which is also known as a wrapper or a translator pattern, converts the interface of a class into another interface expected by a client. It is described in  Chapter 5, Adapter, Decorator, Facade, and Proxy.
  • Bridge pattern: This decouples an abstraction from its implementation, which allows the two to vary independently. This pattern is described inChapter 4, Composite, Flyweight, Marker Interface, and Bridge.
  • Composite pattern: This composes from the hierarchies of more basic objects. This pattern is described inChapter 4, Composite, Flyweight, Marker Interface, and Bridge.
  • Decorator pattern: This pattern allows an object to take additional responsibilities, in addition to its original interface. Decorators are an alternative to subclassing for an extending functionality. This pattern is described inChapter 5, Adapter, Proxy, Decorator, and Facade.
  • Extension object pattern: This pattern allows you to adding of a functionality to a hierarchy without changing that hierarchy. This is not covered in this book.
  • Facade pattern:  This pattern combines a set of interfaces exposed by subsystems into a simpler interface that is easier to use. This pattern is described inChapter 5, Adapter, Proxy, Decorator, and Facade.
  • Flyweight pattern: This pattern uses data-sharing to efficiently support large numbers of similar objects. It is described inChapter 5, Adapter, Proxy, Decorator, and Facade.
  • Front controller pattern: This pattern is used when designing web applications and provides a centralized entry point for request handling. It is not covered in this book.
  • Marker pattern: This allows us to associate metadata with a class. This pattern is described inChapter 4, Composite, Flyweight, Marker Interface, and Bridge.
  • Module pattern: This pattern groups several related elements into one conceptual entity. It is not covered in this book.
  • Proxy pattern: It provides a replacement for another object so it can control access to it. This pattern is described inChapter 5, Adapter, Proxy, Decorator, and Facade.
  • Twin pattern: This pattern helps simulating multiple inheritance in programming languages that don't support this feature. It is not covered in this book.

Behavioral patterns

The third group of patterns, behavioral patterns, deals with communication between objects and with the distribution of responsibilities. The following patterns belong to this group:

  • Blackboard pattern: This is an artificial intelligence (AI) pattern for combining different data sources. It is not covered in this book.
  • Chain of responsibility pattern: This is an object-oriented version of anif ladder idiom (if ... else if ... else if ... else). It works by constructing a chain of processing objects. It is not covered in this book.
  • Command pattern: This pattern encapsulates a request as an object. It is especially useful for building user interfaces where it allows for the support of undoable operations. This pattern is described inChapter 6, Nullable Value, Template Method, Command, and State.
  • Interpreter pattern: This pattern defines a representation of a language grammar and gives an interpreter for that grammar. It is not covered in this book.
  • Iterator pattern: This provides a way to access elements of an aggregate object (list, array, symbol table, tree, and so on) sequentially, without exposing the underlying implementation of that object. This pattern is described inChapter 7, Iterator, Visitor, Observer, and Memento.
  • Mediator pattern: This defines an object that handles interaction between other objects. This pattern supports loose coupling by preventing objects from referring to one another explicitly. It is not covered in this book.
  • Memento pattern: This specifies how to store and restore an object's internal state without violating encapsulation. This pattern is described inChapter 7, Iterator, Visitor, Observer, and Memento.
  • Null object pattern: This removes the reason for using anilpointer, by providing a special, default value for a class. This pattern is described inChapter 6, Nullable Value, Template Method, Command, and State.
  • Observer pattern: This pattern is also known as a publish/subscribe pattern. It provides another way to prevent tight coupling in a system, by setting up a system where a change of objects results in all of its dependents being notified about the change. This pattern is described inChapter 7, Iterator, Visitor, Observer, and Memento.
  • Servant pattern: This pattern defines an object that implements a common functionality for a group of classes. It is not covered in this book.
  • Specification pattern: This pattern provides support for business logic that can be recombined by chaining the rules together with boolean operations. It is not covered in this book.
  • State pattern:This  allows an object to change its behavior when there is a change to its internal state.It is described inChapter 6, Nullable Value, Template Method, Command, and State.
  • Strategy pattern: This pattern defines a family of algorithms that can be used interchangeably. It is not covered in this book.
  • Template method pattern: This defines a skeleton of on operation and defers some steps to subclasses. This pattern is described inChapter 6, Nullable Value, Template Method, Command, and State.
  • Visitor pattern: This pattern specifies an operation that is performed on all elements of an object's internal structure. It is described inChapter 7, Iterator, Visitor, Observer, and Memento.

Concurrency patterns

The last group, concurrency patterns, contains patterns that are needed in the world of parallel programming. The following patterns belong to this group:

  • Active object pattern: This pattern hides the concurrency by implementing asynchronous method inside an object, which serves as a scheduler for handling requests. It is not covered in this book.
  • Binding properties pattern: This pattern combines multiple observers to force synchronization on properties in different objects. It is not covered in this book.
  • Blockchain pattern: This provides a decentralized way for storing data in a linked list protected with cryptographic means. It is not covered in this book.
  • Compute kernel pattern: This pattern executes the same calculation many times in parallel, differing only on integer input parameters. It is frequently related to GPU calculation. It is not covered in this book.
  • Double-checked locking pattern: This reduces the overhead of acquiring a lock in a safe manner. This pattern is described inChapter 8, Locking patterns.
  • Event-based asynchronous pattern: This pattern defines a way of executing parallel operations where a caller is notified when a worker finishes the execution. It is not explicitly described in this book, although it is used as a basis for concrete implementations inChapter 9, Thread pool, Messaging, Future and Pipeline.
  • Future pattern: This pattern pushes a calculation into a background and replaces it with a promise that a result will be available in the future. It is described inChapter 9, Thread pool, Messaging, Future and Pipeline.
  • Guarded suspension pattern: This pattern manages operations that depend on a two-part condition: a precondition that must be satisfied and a lock that must be acquired. It is not covered in this book.
  • Join pattern: This pattern provides a way to write distributed and parallel systems, by message passing. It is not covered in this book.
  • Lock pattern: This protects shared resources by implementing a locking mechanism. This pattern is described inChapter 8, Locking patterns.
  • Lock striping pattern: This pattern optimizes locking, by replacing a single global lock with a set of specialized locks. It is described in Chapter 8, Locking patterns.
  • Messaging design pattern (MDP): This is based on the interchange of information between components in the system. This pattern is described inChapter 9, Thread Pool, Messaging, Future,and Pipeline.
  • Monitor object pattern: This pattern combines locking with a mechanism for signalling other threads that their condition was met. It is not covered in this book.
  • Optimistic initialization pattern: This reduces the cost of locking by replacing it with the small probability of extraneous objects being created and thrown away. This pattern is described inChapter 8,Locking patterns.
  • Pipeline pattern: This pattern specifies a way of decoupling thread dependencies by passing small subsets of data from one worker thread to another through a message-passing pipeline. It is described inChapter 9, Thread Pool, Messaging, Future, and Pipeline.
  • Reactor pattern: This is a reactor object that provides an asynchronous interface to resources that must be handled synchronously. It is not covered in this book.
  • Read-write lock pattern: This allows multiple objects to simultaneously read a shared resource, but forces exclusive access for write operations. This pattern is described inChapter 8,Locking patterns.
  • Scheduler pattern: This pattern controls when threads may execute single-threaded code. It is not covered in this book.
  • Thread pool pattern: This is a parallel version of an object pool creational pattern that provides a pool of worker threads that execute numerous tasks. It is described inChapter 9, Thread Pool, Messaging, Future, and Pipeline.
  • Thread-specific storage pattern: This allows us to use global memory that is local to a thread. In Delphi, we implement this by declaring a variable with thethreadvardirective. It is not covered in this book.