Học phần này giới thiệu cho sinh viên các khái niệm cốt lõi của lập trình cùng với phần giới thiệu về các thuật toán và đặc điểm của mô hình lập trình. Trong số các chủ đề trong phần này bao gồm: giới thiệu về thuật toán, lập trình hướng đối tượng và hướng sự kiện, các cân nhắc về bảo mật, môi trường phát triển tích hợp và quy trình gỡ lỗi.
OOP GENERAL CONCEPTS
Object-oriented programming (OOP)
Object-oriented programming (OOP) structures computer programs around data (objects) rather than functions and rules, where each object combines data and actions.
OOP is useful for big and complex programs that change often It's great for things like making software for manufacturing or mobile apps, even simulating manufacturing systems
Object-Oriented Programming (OOP) facilitates collaborative software development, enabling code reuse, scalability, and efficiency.
There are several advantages of OOP including:
Modularity: Objects are like self-contained units, making it easier to find and fix problems, and to work together on projects
Reusability: You can reuse code, so you don't have to write the same stuff over and over
Productivity: You can create new programs faster using pre-made code and libraries
Upgradability and Scalability: You can update different parts of a program without messing up the whole thing
Security: Complex stuff is hidden, making it easier to keep software safe and protect online data
Flexibility: Objects can change and work in different ways, making them adaptable, and different objects can use the same methods
On the other hand, OOP also contains a certain number of disadvantages, they are:
Steep Learning Curve: OOP is tough to learn, especially for beginners Concepts like inheritance, polymorphism, and encapsulation can be tricky to grasp
Overhead: OOP code can be wordy and might run slower It often needs more memory and processing power compared to other coding styles
Complexity: OOP can make your code complex, especially in big systems with lots of linked objects This makes debugging and maintaining the code harder.
Object and class
A class serves as a blueprint for creating objects, defining their characteristics and behavior Class descriptions include the object's properties and methods.
Attributes, which are like characteristics or properties, and
Methods, which are like actions or functions
Classes in object-oriented programming serve as blueprints, defining common attributes and behaviors for objects of a specific type This approach promotes code reusability, a key advantage over procedural programming.
Mobile phones, with attributes like brand and RAM, and functionalities such as texting and calling, serve as a class example in object-oriented programming This class represents all individual phones (objects).
This MobilePhone class would include 2 attributes named “name” and “ram”, and 2 public methods which are Texting and Calling
Figure 2 Class diagram of MobilePhone
A C# implementation of a MobilePhone class diagram uses a string attribute for "name" and an integer attribute for "ram." The `Texting()` and `Calling()` methods are void, returning no values.
An object is a single instance of a class, and it holds both data and the actions that work with that data So, an object has three parts:
Name: This is a variable name or identifier for the object
Member data: These are the details that define the object, like its properties
Methods: These are the functions that tell you what the object can do, its behaviors
For instance, take an iPhone It's an object with the name "Iphone X” and “2” GB of RAM as its properties, and the behaviors of making calls and sending texts
Instantiating the `MobilePhone` class (created January 3rd) generates an object named "Iphone X" with 2GB RAM Assigning `mobilePhone = new MobilePhone;` creates a new `MobilePhone` object.
Classes are blueprints defining the properties and behaviors of objects Each object is a class instance, inheriting its characteristics and actions.
Classes are blueprints for objects; object creation allocates memory on the heap to store their data and methods.
Table 1 Class and Object Comparison
A class is a blueprint for declaring and creating objects
An object is a class instance that allows programmers to use variables and methods from inside the class
Memory is not allocated to classes Classes have no physical existence
When objects are created, memory is allocated to them in the heap memory
You can declare a class only once A class can be used to create many objects
Class is a logical entity An object is a physical entity
Classes can have attributes and methods defined Objects can have specific values assigned to their attributes.
Encapsulation
Encapsulation restricts direct access to an object's internal variables and functions, maintaining data privacy and controlled access This technique protects an object's inner workings by hiding its data and methods.
The advantages of encapsulation are:
Data Protection: Encapsulation prevents the program from altering variables or data, enhancing security and stability
Flexibility: Encapsulated code is cleaner and adaptable It can be made read-only or write-only using getter and setter methods, which aids in code maintenance and debugging
Reusability: Encapsulated methods can be easily modified and reused
However, there are some disadvantages:
Code Size: Encapsulation can make code longer because you need to provide access methods with specific specifiers
More Instructions: With increased code size, you'll need to provide additional instructions for each method
Increased Code Execution Time: Encapsulation can lead to longer program execution times as more instructions are added, requiring more time to execute
Aftern learning the encapsulation in OOP so that I will encapsulate two properties “name” and “ram” with private keyword and access them via public properties Name and Ram
Encapsulation in object-oriented programming (OOP) is demonstrated by using private variables, like `name` and `ram`, accessed through public fields, `Name` and `Ram` This controlled access protects data integrity.
When I encapsulate the properties so they cannot be accessed outside its class and I set their properties via Name and Ram
Figure 7 Code implementation in Main
Inheritance
Inheritance in object-oriented programming promotes code reuse by allowing classes to inherit attributes and methods from parent classes, effectively gaining their characteristics and behaviors.
Subclasses (also known as child or derived classes) inherit from parent classes (also known as superclasses or base classes).
It's important to note that some languages, like Go, use composition instead of inheritance
Composition is an alternative approach where complex objects are created by combining or aggregating other objects Many object-oriented programming languages offer both composition and inheritance for code organization
Code Reuse: Inheritance allows you to reuse common code among different classes
Code Design: Inheritance is essential for designing well-structured code, especially when multiple developers work on the same project
Polymorphism: Inheritance enables different classes to be treated as objects of the same class, promoting flexibility
Encapsulation: It allows for hiding implementation details from external users, providing privacy and structure through multiple levels of inheritance and private classes
Tight Coupling: Changes in the parent class can impact the child classes, potentially causing unintended issues Proper class design is crucial to avoid this problem
Fragile Base Class Problem: Incomplete base classes can lead to significant issues in derived classes when changes are made to the base class
Multiple inheritance, where a class inherits from two or more classes, can lead to the diamond inheritance problem: conflicts arise when a subclass inherits methods with the same name from multiple superclasses This ambiguity is why some languages, such as Java, prohibit multiple inheritance.
Inflexibility: Derived classes need to follow the structure of the base class, limiting their independence compared to stand-alone classes
Increase in Code Complexity: Excessive use of inheritance can make code collaboration difficult and result in unnecessarily complex code structures
OOPs support the six different types of inheritance, including:
In this type of inheritance, a child class is derived from a single parent class
Class B inherits attributes and behaviors from its parent class, Class A (superclass), making it a subclass.
In this type of inheritance, a child class is created from another child class
Multilevel inheritance occurs when Class C inherits from Class B, which in turn inherits from Class A This creates a chain where Class C inherits properties and behaviors from both Class A and Class B.
Figure 9 Multi-Level inheritance illustration
In this type of inheritance, a child class is created from more than one base class It's commonly known as multiple inheritance
However, it's important to note that not all programming languages support multiple inheritance Languages like C#, F#, and Java do not support this type of inheritance
In the example, Class C inherits the properties and behavior of both Class B and Class A, meaning both Class A and Class B are considered parent classes for Class C, resulting in multiple inheritance
Multipath inheritance, where a derived class inherits from multiple derived classes sharing a common base class, is unsupported by languages like C#, F#, and others within the NET framework.
Class D inherits from Class C and Class B, which both inherit from Class A, forming a multipath inheritance structure where Class A is the common base class.
Multiple derived classes inherit from a single base class, creating a hierarchical inheritance structure where child classes can also serve as parent classes This forms a tree-like class hierarchy.
Class A is the base class with two child classes, Class B and Class D
Class B has two child classes, Class D and Class E
Class C has two child classes, Class F and Class G
This hierarchy demonstrates a complex form of inheritance, where multiple levels of parent-child relationships are established
Hybrid inheritance combines multiple inheritance types (multilevel, multiple, hierarchical, and multipath), creating complex parent-child relationships within the inheritance hierarchy.
C# and other NET languages don't support multiple or multipath inheritance, preventing hybrid inheritance models.
Son class is inherited from Parent class and reuse all what parent class has Moreover, Son class can add more fileds and methods as needed
Base on the class diagram:
There is a private property named “name”, it can be accessed by Name
A public method name “Sing”, all class that inherit from this class can reuse this method without having their own ones
Figure 15 Parent class code implementation
Class Son is inherited from Parent class, there is a new property named “tattoo” A new method Dance() has been created and used in this scope
Figure 16 Son class code implementation
In Main, object son can set name and tattoo without owns its name property Son still Sing which contains in Parent class
Polymorphism
Polymorphism, meaning "many forms," is a core object-oriented programming (OOP) concept enabling functions to exist in multiple types It allows data to take on various forms, a key feature of flexible and adaptable OOP designs.
One common use of polymorphism is when a reference to a parent class is used to refer to an object of a child class This concept is essential in object-oriented programming
Polymorphism, in everyday life, manifests as an individual's ability to assume multiple roles concurrently; for instance, a woman might be a mother, wife, employee, and daughter simultaneously, adapting her behavior based on context.
Polymorphism, a cornerstone of object-oriented programming (OOP), is essential for a language to be considered truly object-oriented; languages with classes but lacking polymorphism are classified as object-based.
Polymorphism empowers object-oriented programming by enabling objects or references to take on different forms in various instances It incorporates concepts like function overloading, function overriding, and virtual functions
Code Reusability: Polymorphism allows programmers to reuse previously written, tested, and implemented code and classes in multiple ways, saving time and effort
Polymorphism allows a single variable to hold different data types (Float, Double, Long, Int), increasing flexibility in data handling.
Reduced Coupling: Polymorphism helps reduce the coupling between different functionalities or components of a program, enhancing modularity and making it easier to manage and maintain
Implementation Complexity: Developers may find it challenging to implement polymorphism correctly in their code, as it requires a solid understanding of object-oriented principles
Run-time polymorphism's decision-making process introduces performance overhead, potentially slowing program execution due to runtime method and variable invocation choices.
Polymorphism, while powerful, can hinder program readability by obscuring the execution path, thus complicating understanding and debugging.
Class Animal contains a public name makeSound() and derived classes when inherit from its parent would redefine this method
Figure 20 Polymorphism class diagram example
The method in base class Animal would be virtual so that all derived classes can override it Each method in each class can define the thethod as different ways
Abstraction
Abstraction simplifies complex systems in computer science and object-oriented programming (OOP) by modeling classes with essential properties and behaviors, hiding unnecessary details.
Real-world machines utilize abstraction, simplifying complex internal processes for user-friendly interaction Starting a car, for instance, requires only a key or button press; the intricate engine mechanics are abstracted from the user's experience This hides complex logic and components, creating ease of use.
There are two types of abstraction
Data abstraction involves hiding the internal data (attributes or properties) of an object from the external world
External users cannot directly access object data; instead, access is controlled via getter and setter methods.
Users interact with the object by calling these methods, which ensures controlled and secure access to the object's data
Process abstraction, on the other hand, deals with the abstraction of an object's behaviors or methods
It means that you don't need to provide all the details about how each function or method within an object works
The internal implementation of these functions is hidden from external users Instead, users are provided with a simplified and abstracted interface to call these functions
Advantages of Abstraction in OOP:
Simplifies Complex Systems: Abstraction simplifies complex systems by hiding irrelevant details and presenting only the essential information, making it easier to understand
Enhances Code Readability: It improves the clarity and readability of code, making it more understandable and maintainable for programmers
Supports Code Reusability: Abstraction promotes code reusability, allowing you to use the same code in multiple parts of your program, reducing duplication of effort
Modular design significantly improves code maintainability, allowing changes in one area without impacting the entire system, thus enhancing long-term software maintainability.
Disadvantages of Abstraction in OOP:
Complicates Code Understanding: Abstraction can make it challenging for developers to understand the code, especially if they are not familiar with the underlying implementation, as it hides internal workings
Slows Down Program Execution: Using abstract classes or interfaces to implement abstraction can introduce some performance overhead, potentially slowing down program execution
Difficult for New Programmers: New programmers may find abstraction challenging to grasp, as it requires a good understanding of the underlying concepts and implementation
Increases Code Debugging Difficulty: Debugging can become more complex because the actual code execution is hidden behind abstract methods, making it harder to trace and diagnose issues
In Shape class, there is a method named CalculateArea() but it is just a signature without body which is defined in derived classes “Circle” and “Rectangle”
Figure 25 Abstraction class diagram example
Declare Shape as abstract with an abstract method which does not contain body
Figure 26 Shape abstract class code implementation
In derived classes, describe the body in the abstract method in base class
Figure 27 Circle class code implemetation
Figure 28 Rectangle class code implementation
When executing the program, each method will display different values with different algorithms
DESIGN AND BUILD CLASS DIAGRAMS USING UML TOOLS
Theory of UML
Unified Modeling Language (UML) uses visual diagrams to model software and business processes, offering a clear, concise way to identify potential problems and improve understanding These diagrams facilitate efficient communication and problem-solving, illustrating complex systems effectively.
UML, standardized in 1997, revolutionized software system design by unifying diverse, previously confusing methodologies Developed by Rational Software engineers in the 1990s, it remains a prevalent standard for creating software diagrams.
UML, initially used for software design, now also documents business processes Activity diagrams, a key UML component, provide superior flowchart functionality, enabling standardized workflow visualization and enhanced clarity.
There are two main categories: structural diagrams and behavioral diagrams
Figure 30 Types of UML diagrams
Diagrams
In this session, there are several types of UML diagrams; therefore, I will concentrate on some prevalent types and describe details about them
These days, people often connect use case modeling with UML, even though it existed before UML Here's a quick history:
In 1986, Ivar Jacobson came up with ways to describe use cases using words and pictures
In 1992, he co-wrote a book about Object-Oriented Software Engineering that made this method more popular, especially in software development
UML use case diagrams visually represent user interactions with a system, illustrating system functionality from the user's perspective These diagrams define system requirements and depict how users or systems achieve specific goals.
System diagrams visually represent features and user/system interactions, clarifying requirements for stakeholders They define system boundaries and aid development and testing.
Use case diagrams include four main objects:
Table 2 Symbols of Use Case diagram
Actor: An actor is something, like a person, an organization, or an external system, that plays a role in a system It's usually represented as a simple outline
Use Case: A use case is a specific function or action within the system It's depicted as an oval shape and labeled with the function it represents
Use systems diagrams, represented as rectangles, to define the scope of large projects and delineate areas for phased releases While optional, they enhance clarity and organization.
Packages, optional but especially useful for complex diagrams like class diagrams, group related use cases, improving diagram organization.
Use case diagrams illustrate relationships between use cases, reflecting system dependencies Strategic use of these relationships simplifies system development.
Table 3 Relationship in Use Case diagram
Use case extension adds optional or conditional behavior to a base use case This relationship enables one use case to modify another's functionality under specific circumstances.
Include: When one use case includes the functionality of another as part of its business process, the "include" relationship is used to depict this relationship
Generalization: It illustrates a parent-child relationship, where one use case is a more specialized version of another, inheriting its behavior
Pros of a Use Case Diagram:
Simplicity: Use case diagrams are easy to understand and use simple notation, making them accessible to a wide range of stakeholders
User Types: They provide an overview of all the user types that will interact with the system, helping to identify and categorize user roles
User Interactions: Use case diagrams show potential user interactions, making it clear how users will engage with the system
Visual Representation: They create a simple visual representation of even complex systems, making it easier to communicate and comprehend system behavior
Cons of a Use Case Diagram:
Lack of System Details: Use case diagrams focus on the interactions between users and the system, so they don't capture the internal details of the system's functionality
User Orientation: These diagrams are user-oriented and may not represent the full system functionality or technical aspects
Abstraction: In some cases, use case diagrams might become too abstract, which can make it challenging to capture all the nuances of a complex system
Use Case Diagrams visualize the interactions between users, administrators, authentication systems, and payment methods during the typical product purchase process, clarifying how each actor contributes to completing the transaction.
Figure 31 UseCase of Inventory management system
Product browsing and searching are accessible to all users without requiring authentication Purchase and cart actions, however, necessitate user authentication Secure payment processing is crucial for completing purchases Administrative product modifications also require authentication.
Class UML diagrams are essential for software documentation, especially for Object-Oriented Programming (OOP) systems, due to their focus on classes and their relationships.
Class diagrams visually represent classes, their attributes (data), and behaviors (functions) Each class displays its name, attributes, and behaviors, with connecting lines illustrating relationships between classes.
In other words, class diagrams help us understand the structure of software by showing how classes are organized and connected
In a Class Diagram, certain symbols and notations are used to convey specific information:
"+" denotes public attributes or operations
"-" denotes private attributes or operations
"#" denotes protected attributes or operations
1) Inheritance: Inheritance arrows are used to indicate that a child class inherits functionality from the parent class For example, Dog is inherited from Animal
2) Association: Represents any type of relationship or connection between classes For example, passengers and airplane can be linked as below
3) Aggregation: Shown with aggregation arrows, it signifies that two classes are associated but not as closely as in direct association The child class can exist independently of the parent element For example, the relationship between library and book, when the libray does not exist anymore, book still exists
4) Composition: Displayed with composition arrows, it indicates a relationship similar to aggregation but with a key difference Composition associations reveal that the sub-object exists only as long as the container class exists The classes share a common lifecycle For example, when the person is dead, all organs would be died
5) Realization/Implementation: Realization or implementation arrows are used to denote a place where one class implements the functions defined in another class For example, class Dog implements from Animal
Flexibility: Class diagrams are crucial in different project phases and form the foundation for software projects
Structural Insight: They provide a clear view of system structure and element interactions
Clarity and Ease of Use: Class diagrams are fast to read and vital for system development Disadvantages of Class Diagrams:
Lack of Clarity for Some Roles: Not all stakeholders find class diagrams equally useful; simpler tools might be preferred
Complexity Challenges: Overly detailed diagrams can be confusing and counterproductive
Overemphasis on Design: Focusing too much on design can hinder actual development work; balance is essential
Below you can see an example of a simple class diagram
The Parent class contains a private string field, `name`, encapsulated by a public field, `Name`, providing access to the private field It includes `Sing()` and an overridden `ToString()` method.
The `Son` class extends `Parent`, adding a string field "tattoo" and a `Dance` method It maintains an aggregation relationship with the `Toy` class; `Son` persists even if `Toy` is removed.
Sequence diagrams visually depict the step-by-step interactions between actors and objects in software systems, providing a chronological representation of message exchanges crucial for computer science and business application development.
Table 4 Notations of Sequence diagram
DESIGN PATTERN
Overview
Software design patterns are documented, reusable solutions to common software design problems, emerging from recurring issues across multiple projects.
The concept of patterns was initially described by Christopher Alexander in his book "A Pattern
Language: Towns, Buildings, Construction." He applied it to urban and architectural design
In the realm of software, Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm published
"Design Patterns: Elements of Reusable Object-Oriented Software" (1994) introduced 23 foundational object-oriented design patterns, sparking widespread adoption and the subsequent development of numerous patterns across diverse programming paradigms.
Software design patterns offer reusable solutions to common coding problems They provide flexible blueprints, adaptable to various challenges, rather than concrete code These patterns represent general concepts for tackling specific coding issues.
Design patterns provide high-level solution descriptions, offering flexibility in implementation, unlike algorithms which give precise, step-by-step instructions Think of design patterns as blueprints and algorithms as recipes.
Design patterns offer diverse solutions to software problems, ranging from simple fixes to complex, comprehensive architectures, much like choosing between a traffic light or a multi-level interchange for improved road safety.
There are three main categories of design patterns:
Creational patterns: These help with creating objects in a flexible and reusable way
Structural patterns: They guide the assembly of objects and classes into larger, flexible, and efficient structures
Behavioral patterns: These focus on ensuring effective communication and responsibilities between objects
Design patterns offer solutions spanning low-level coding idioms to high-level application architectures; selecting the appropriate pattern for a given problem is crucial.
3 Advantages and disadvantages of design patterns
Design patterns offer several advantages:
Reusability: Design patterns provide reusable solutions to common problems, saving time and effort in multiple projects
Efficiency: They help developers quickly address specific issues, reducing time spent on problem-solving
Quality: Using established design patterns can enhance software quality and reliability
Value for Money: Design patterns provide a solid foundation for software development, offering long-term benefits and cost-effectiveness
Proven Solutions: Design patterns are well-tested and proven solutions, making system extension and enhancement easier
Risk Reduction: They reduce the risk of implementing short-term solutions that may not work well in the long run
Stability: Design patterns can reduce the need for frequent code changes and improve system stability
However, they also have limitations:
Decision Complexity: Deciding when and which design pattern to use can be challenging
Generic Nature: Design patterns may not always fit specific requirements, requiring adaptation and customization
Expertise Required: Proper implementation of design patterns requires a certain level of expertise
Potential for Errors: Inexperienced teams may struggle with correct implementation, leading to bugs and delays.
Creational patterns
The Singleton pattern guarantees a class has only one instance, accessed globally This solves the problem of needing a single object instance, often with lazy initialization The Singleton class manages its own creation, initialization, and access, using a private static member for the instance and a public static member function for access.
The Singleton pattern should be considered when:
Ownership of the single instance cannot be reasonably assigned
Lazy initialization (creating the instance only when needed) is desired
Global access to the instance is needed
The Singleton pattern is unnecessary unless specific criteria are met; however, it can be adapted to manage multiple application instances.
The Singleton design pattern offers global access to a single instance, simplifying access throughout the program It's ideal for modeling unique real-world entities like registration offices or global timers, improving code clarity by aligning program structure with reality.
Overusing the Singleton pattern, often for unnecessary demonstration, leads to inefficient code where a simple class instance would suffice Modifying a Singleton necessitates creating a new class, increasing memory consumption.
Make the class create an instance on first use and then only use but not create, and provide a way to access that instance globally via a public method
The static `GetInstance()` method provides lazy instantiation of a singleton object It creates a new singleton only on the first call, subsequently returning the same instance.
Figure 41 Singleton class code implementation
Singleton instantiation is vulnerable to multithreading issues; concurrent access can create multiple instances Thread-safe implementations prevent this duplication by ensuring only one instance is ever created, regardless of concurrent access attempts The provided code demonstrates a thread-safe solution.
Structural patterns
The Facade design pattern simplifies access to complex subsystems by providing a unified, higher-level interface This reduces complexity for clients, lowers the learning curve, and promotes decoupling, making it particularly useful when only a subset of users need simplified interaction with the subsystem's full functionality.
The Facade design pattern offers advantages such as reduced coupling between subsystems, simplifying modification, testing, and reuse, and a user-friendly interface that hides complexity However, disadvantages include potential performance overhead due to added abstraction layers and limited client control over system functionality.
The Facade pattern simplifies complex subsystems by providing a unified interface A Facade class hides the internal complexities of multiple subsystems, offering a single point of access for clients.
SubsystemA and SubsystemB classes represent parts of a more complex system They have their own methods and functionalities, but clients don't need to interact with them directly
A Facade class simplifies interactions with subsystems (SubsystemA and SubsystemB) by providing a unified interface Its constructor initializes subsystem instances, and its `DoTasks` method coordinates their operations.
When executing the code, I just need to create an instance of Faỗade class, all subsystems have also run as well
Behavioral patterns
The Command pattern, a behavioral design pattern, encapsulates requests as objects, enabling parameterized requests, queuing, logging, and undo functionality This abstraction decouples request issuers from the receiving objects and their specific operations.
Command classes encapsulate an object, a method, and its arguments The `execute` method orchestrates these components to perform the operation.
The Command pattern has these advantages:
It separates the classes that initiate an operation from the object that performs it
It enables the creation of a sequence of commands using a queue system
Adding new commands is straightforward and doesn't require changing existing code
You can establish a rollback system with the Command pattern, allowing actions to be undone The disadvantages of the Command pattern are:
It involves a significant number of classes and objects collaborating, which requires careful development
Each individual command becomes a ConcreteCommand class, leading to an increased number of classes to manage during implementation and maintenance
The code consists of three classes: Receiver, ICommand (an interface), and Sender Receiver can perform "OperationA" and "OperationB," while ICommand defines methods for commands
ConcreteCommand implements ICommand, executing "OperationA" and undoing "OperationB." Sender manages command execution and undo
Receiver Class: This class represents the entity that carries out specific operations It contains two methods: OperationA() and OperationB(), which represent distinct tasks
Figure 49 Receiver class code implementation
The Command Interface defines a contract for command objects, mandating `Execute()` and `Undo()` methods to perform and reverse operations, respectively.
The ConcreteCommand class implements the ICommand interface, invoking Receiver's OperationA() in its Execute() method and OperationB() in its Undo() method.
Figure 50 ICommand and Concrete code implementation
The Sender class executes commands via its `SetCommand()` and `ExecuteCommand()` methods, also providing `UndoCommand()` functionality.
Figure 51 Sender class code implementation
Firstly, create an instance of the Receiver class and then pass this instance to the object of
ConcreteCommand Creates Sender object and sets the command using the SetCommand() method
It calls ExecuteCommand() on the Sender, which, in turn, invokes the Execute() method of the stored command, executing OperationA() on the Receiver
It calls UndoCommand() on the Sender, which invokes the Undo() method of the stored command, effectively executing OperationB() on the `Receiver
DESIGN PATTERN AND OOP
Relationship between OOP and Design pattern
Object-Oriented Programming (OOP) is like building with LEGO bricks, where code is organized into different pieces that represent objects and their relationships
Design Patterns are like well-tested recipes for creating these code pieces to solve specific problems in a program They're like handy shortcuts for common coding challenges
Understanding common design patterns, prevalent in languages like Java and NET, improves programmer efficiency and code comprehension, enabling better integration of program components, similar to assembling complex LEGO structures.
Object-oriented programming (OOP) principles like encapsulation and abstraction are fundamental to design patterns Encapsulation hides internal object details, exposing only necessary interfaces for interface-based interactions crucial to many patterns Abstraction enables generalized structures, readily extended or implemented by design patterns.
Inheritance and polymorphism are crucial to design patterns, enabling class hierarchies and flexible, interchangeable components through inheritance and interfaces.
Analyzing OOP through design patterns
The Singleton pattern in object-oriented programming (OOP) ensures a class has only one instance, providing global access via a single point This pattern encapsulates instance creation and access, ideal for coordinating actions requiring a single instance This exemplifies OOP's encapsulation principle.
Figure 54 Singleton pattern class diagram
The Facade pattern simplifies complex subsystem interactions (SubsystemA, SubsystemB) by providing a higher-level interface, encapsulating subsystem details and promoting easier usage.
The Facade design pattern simplifies complex subsystem interactions by providing a single, easy-to-use interface Clients interact with the Facade, abstracting away intricate internal workings This leverages encapsulation and abstraction principles.
Figure 55 Facade pattern class diagram
The Command pattern encapsulates requests as objects, each ConcreteCommand executing and optionally undoing a specific operation This promotes modularity and separation of concerns via the ICommand interface's polymorphism, enabling diverse command execution.
(ConcreteCommand) to be treated uniformly when executed and undone This promotes flexibility and extensibility in handling various commands
Figure 56 Command pattern class diagram
Analyzing OOP through scenario
Figure 57 Airplane ticket system's class diagram
In my airplane ticket selling system, I have several components that demonstrate the use of various design patterns and OOP principles, including:
Passengers are objects representing individuals using my system
Flights are objects representing specific airline journeys
Cities are objects representing locations that flights connect
Airplanes are objects representing aircraft used for flights
The Service class, implemented as a Singleton, serves as a central service that connects to a database It follows the Singleton Pattern to ensure a single, globally accessible instance
The TicketFactory demonstrates the Factory Method Pattern It abstracts the creation of different types of flight tickets (StandardTicket, BusinessTicket, VipTicket)
The Ticket interface defines the common structure for all types of flight tickets
I will mainly focus on Service and Ticket Factory to emphasize the relationship between OOP and design patterns:
Encapsulates the creation and management of a single instance of the Service class, ensuring that its implementation details are hidden from the rest of the application
This service manages database connections, abstracting complexities from the application The application interacts solely with the service class, simplifying development and maintenance.
Polymorphism simplifies ticket object creation; client code remains unaware of specific ticket classes.
Defines an interface for creating Ticket objects, which encapsulates the logic for selecting the appropriate type of ticket The abstraction simplifies the client code that needs to create tickets
The Factory Method pattern uses a common `Ticket` interface, enabling uniform treatment of diverse ticket classes like `StandardTicket`, `BusinessTicket`, and `VipTicket`, which inherit from it.
Singleton and Factory Method patterns embody core OOP principles (encapsulation, abstraction, polymorphism, inheritance), enabling flexible, maintainable, and scalable system design.
In conclusion, this report provided a comprehensive overview of Object-Oriented Programming (OOP) and various aspects related to it The key takeaways from the report include:
Understanding OOP Basics: The report covered fundamental OOP concepts such as Encapsulation, Inheritance, Polymorphism, and Abstraction These principles are the building blocks of object- oriented design
UML class diagrams are essential for system analysis and design This guide explains their concepts, symbols, and practical applications through various examples Master different UML class diagram types for improved comprehension.
This report explores object-oriented coding principles and design patterns, providing examples of various pattern types and illustrating their strong relationship with OOP.
I extend my sincere gratitude to Mr Nghia for his invaluable guidance and unwavering support, significantly enhancing my understanding of the subject His dedication and assistance were instrumental to my learning journey.
Gillis, A S and Lewis, S (2021) What is object-oriented programming (OOP)?, App Architecture,
TechTarget, [online] Available at: https://www.techtarget.com/searchapparchitecture/definition/object-oriented-programming-OOP (Accessed 7 October 2023)
Nishad, A (n.d.) Classes and objects in Object Oriented Programming, enjoyalgorithms, [online]
Available at: https://www.enjoyalgorithms.com/blog/classe-and-object-in-oops (Accessed 7 October
Tripathi, S (2021) Difference between class and object, Scaler Topics, Scaler Topics, [online] Available at: https://www.scaler.com/topics/difference-between-class-and-object/ (Accessed 7 October 2023)
Reddy, R (2023) 4 advantages and 6 disadvantages of inheritance, OpenGenus IQ: Computing Expertise
& Legacy, OpenGenus IQ: Computing Expertise & Legacy, [online] Available at: https://iq.opengenus.org/advantages-and-disadvantages-of-inheritance/ (Accessed 7 October 2023)
This article from DotNetTricks provides a comprehensive understanding of inheritance in object-oriented programming, covering various inheritance types It's a valuable resource for interview preparation and enhancing OOP skills.
Anon (2023) Perl: Polymorphism in oops, GeeksforGeeks, GeeksforGeeks, [online] Available at: https://www.geeksforgeeks.org/perl-polymorphism-in-oops/ (Accessed 7 October 2023)
Pankaj (2022) What is abstraction in oops?, DigitalOcean, DigitalOcean, [online] Available at: https://www.digitalocean.com/community/tutorials/what-is-abstraction-in-oops (Accessed 7 October
Learn about UML diagrams, their various types, and practical examples through resources like Tallyfy's comprehensive guide and Gleek's developer-focused diagrams.
Anon (n.d.) What is use case diagram?, [online] Available at: https://www.visual- paradigm.com/guide/uml-unified-modeling-language/what-is-use-case-diagram/ (Accessed 10 October 2023b)
Harry (2023) A quick guide, Use Case Diagram, [online] Available at: https://boardmix.com/tips/what-is- use-case-diagram-online/ (Accessed 11 October 2023).