This exercise earns Merit points in C programming. This exercise presents design patterns, especially the Strategy pattern, APIE rules in objectoriented programming, exception handling, and error handling.
Introduction
This report presents an illustrative scenario to demonstrate the application of object-oriented design and analysis, aiming to explore the fundamental aspects of the object-oriented programming paradigm (OOP) Through this example, we aim to elucidate various OOP principles such as abstraction, polymorphism, inheritance, and encapsulation We have included diagrams and code representations for each wallet, highlighting their OOP characteristics Providing a practical example facilitates better understanding We will also supply examples and explanations for each type of diagram mentioned earlier Additionally, we will introduce the concept of design patterns, categorized into three types: creational, structural, and behavioral These patterns will be illustrated using diagrams within real-world scenarios, with discussions on how to implement them using UML classes and C# programming techniques.
OOP general concepts
Define and Structure of object-oriented programming
Object-oriented programming (OOP) can be easily understood as creating a digital representation of a real-world object This approach allows users to interact with the program as if they are dealing with an actual object OOP has become a prevalent method in programming, though it's not always necessary as many programs can still be developed without it The key benefit of OOP lies in its code organization, which becomes increasingly vital as the project size and complexity grow OOP mandates thorough planning before coding begins, ensuring that the code adheres to a predefined structure from start to end This organized approach greatly simplifies the process of locating and resolving errors in the code (geeksforgeeks, 2023)
This provided example demonstrates the use of Object-Oriented Programming (OOP) to create a model of a dog In this model, the 'Dog' class acts as a blueprint for depicting a dog This class is responsible for defining various aspects of a dog, including its shape, size, name, age, and behaviors, which are displayed in the main program
The model illustrated consists of four key components: class, object, attribute, and method In this context, the 'Dog' class represents a generic category of dogs, encompassing various breeds like Alaska, Belarus, Dogo, etc This class is equipped with specific attributes such as weight, height, and preferred food, which characterize a dog Additionally, it outlines common actions like running, playing, and eating that all dogs are capable of Each individual dog is an object of the 'Dog' class, identifiable by unique attributes like its name While the 'Dog' class is a broad category, the specific properties, methods, and objects within it allow for the differentiation of each unique dog within the larger class This approach showcases how OOP can be used to organize and represent complex entities in a structured and understandable manner
Figure 2: OOP class diagram example image b Class
In object-oriented programming (OOP), a class functions as a template for constructing objects, and each class is designed with a distinct purpose to describe a particular object Users create custom objects by employing the 'class' keyword for their definition A class essentially encapsulates a predefined set of plans, detailing how objects should be structured and behave Within a class, users define various components like attributes, objects, and methods
Referring to the earlier dog example, the class represents the framework for creating a dog's representation This class lays out all the specific details of the dog, such as its characteristics and behaviors Attributes, objects, and methods unique to the dog are all intricately defined within the class, providing a comprehensive and organized way to represent the dog in a programming context This exemplifies how classes in OOP serve as foundational structures that outline the specifics of what they represent c Object
An object is a fundamental concept to consider when creating your program It represents entities that hold values and perform tasks within a computer system Objects can belong to a common class, and many such classes are employed to define reusable components in code Each object is either an instance of a subclass or an entire class, and each object possesses its own set of methods, procedures, and data types (geeksforgeeks, 2023)
All private objects share three essential characteristics:
Identity: Each object has a unique identifier that distinguishes it from all others
State: This refers to the properties or attributes of an object
Behavior: It signifies the actions or functions that an object can carry out
Objects can be used to define various things, such as data structures, functions, and methods For instance, in the example of a dog, an object could be created to represent the dog itself, and additional objects like the dog's name and age can be utilized to make it easier to identify and work with the dog d Attributes
Properties reside within classes or objects and can manifest as distinct qualities in layers or objects An attribute can be thought of as a trait inherent to the class that houses it Attributes enable classes to interact with other objects and differentiate them from one another (geeksforgeeks, 2023)
In the context of the previously mentioned dog description example, attributes represent specific characteristics of the dog, such as its weight, height, and preferred food These attributes serve as unique identifiers for each dog, allowing users to differentiate between individual dogs, as not all dogs share the same characteristics e Method
A method is quite similar to a function in that it can yield a result based on the type of data initially defined for that method It resembles a function in procedural programming as well Methods can accept input values, carry out instructions, and produce outcomes, much like functions However, the distinction lies in how methods are categorized based on the objectives of the class they belong to Methods operate within the context of classes (geeksforgeeks,
Illustrating this with the example of a dog, consider methods like "Run()," "Play()," and "Eat()." These methods are designed to enforce specific actions related to a dog's running, playing, and eating behaviors When invoked, these methods can modify the attributes associated with the corresponding activities of the dog f Constructor
In object-oriented programming, a constructor is a specific method within a class or structure that initializes a newly created object of that type The constructor is automatically called whenever an object is instantiated It allows for the assignment of values to the members of an object, either through default values or values provided by the user A constructor is similar in concept to an instance method and typically shares the same name as the class it belongs to However, it's important to note that the constructor differs in that it lacks a defined return type When used without any parameters, the constructor sets the object's members to their default values, and when parameters are provided, they are directly used to initialize the object's attributes (geeksforgeeks, 2023)
As an illustration, let's consider an object called "Dog" that includes two constructors The default constructor, "Dog()," does not possess information about the dog's name, while the constructor with a parameter, "Dog(string name)," takes in the dog's name as a string parameter This means that when creating an instance of the "Dog" object, you can provide a name for the dog as an argument to this constructor Furthermore, it's possible to create a constructor that accommodates multiple parameters, each carrying values like weight and height For instance, you could have a constructor like "Dog(string name, double height, double weight)," where you provide the name, height, and weight of the dog when initializing the object
2.2 4 principles of object-oriented programming (APIE)
Abstraction in OOP is about focusing on essential aspects while ignoring the specifics It's used to create simple models representing more complex underlying code structures Abstraction is realized through interfaces or abstract classes
For example, an abstract PaymentProcessor class could define a method processPayment() without specifying how the payment processing is done Classes like CreditCardProcessor and PayPalProcessor would then extend this abstract class and provide specific implementations for processPayment() This abstraction allows users of these classes to utilize different payment methods without understanding the underlying complexities (Monus, 2023)
● The PaymentProcessor class is an abstract class, indicated by the keyword It defines the method +processPayment(): void without implementing it.
● The CreditCardProcessor class extends the PaymentProcessor class, providing a specific implementation of the processPayment() method.
● The PayPalProcessor class also extends PaymentProcessor, with its own implementation of processPayment().
● The arrows from CreditCardProcessor and PayPalProcessor to PaymentProcessor indicate that they are subclasses, inheriting the abstract method and providing concrete implementations.
The SOLID Principles of Object-Oriented Programming
In the realm of Object-Oriented Programming (OOP), SOLID represents an acronym coined by Michael Feathers It encapsulates five design principles employed to enhance the comprehensibility, adaptability, and ease of maintenance in software design It's worth noting that these principles constitute just a portion of the broader set of design principles advocated by Robert C Martin
One class should only have one responsibility and only change its for one reason For example: in the image below describe one class handle two thing at a time, including handle input data and analysis data This example violate the Single
Responsibility Principle If we change how data input in GetInputData, we will also need to change the AnalysisData
Figure 8: Single Responsibility Principle example
A class is always expandable if needed, but to do so we should not directly change the main class Instead we should create a new class to extend the old class by using inherit or so (authoranuupadhyay, 2022)
Figure 9: Open-Closed Principle example
The principle was introduced by Barbara Liskov in 1987 and according to this principle “Derived or child classes must be substitutable for their base or parent classes“ This principle ensures that any class that is the child of a parent class should be usable in place of its parent without any unexpected behavior (authoranuupadhyay, 2022)
Figure 10: Liskov Substitution Principle example
The image above describes three birds including an owl, Sparrow and Penguin However, the Bird class has a fly function that all of its children could inherit But this is a false use due to the fact that the Penguin could not fly So this example did not follow the Liskov Substitution Principle (authoranuupadhyay, 2022)
Instead of using one large interface, we should split it into many small interfaces, with many specific purposes
Figure 11: Interface Segregation Principle example
As shown in the image above, the WoodSpoon and WoodChair both inherit from the WoodTool interface However there are some properties and functions that the wood chair and the wood Spoon need
There are two key point to keep in mind in this principle: High-level modules/classes should not depend on low-level modules/classes Both should depend upon abstractions Abstractions should not depend upon details Details should depend upon abstractions It simply states that if a high module or class will be dependent more on low-level modules or class then your code would have tight coupling and if you will try to make a change in one class it can break another class which is risky at the production level
So always try to make classes loosely coupled as much as you can and you can achieve this through abstraction
While this may sound abstract in theory, it's actually quite easy to grasp with a real-world example Consider a clothing store that offers a policy of free returns within 3 days for products with quality issues or description mismatches However, when shipping, the store owner may not have visibility into the condition of all products As a result, some defective items may reach the customer, and in such cases, the interface allows the customer to initiate a free return within 3 days This illustrates the importance of the clothing store consistently ensuring customer satisfaction, where the interface serves as the means through which customers can return products
Figure 12: Dependency Inversion Principle example
trees
Design Patterns
In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design A design pattern isn't a finished design that can be transformed directly into code It is a description or template for how to solve a problem that can be used in many different situations (sourcemaking, n.d.)
Class instantiation is the central theme of these design patterns Class-creation patterns and object-creational patterns are two subcategories of this pattern Object-creation patterns accomplish tasks through delegation, whereas class-creation patterns exploit inheritance to their advantage throughout the instantiation process (sourcemaking, n.d.)
● Abstract Factory: Creates an instance of several families of classes
● Builder: Separates object construction from its representation
● Factory Method: Creates an instance of several derived classes
● Object Pool: Avoid expensive acquisition and release of resources by recycling objects that are no longer in use
● Prototype: A fully initialized instance to be copied or cloned
● Singleton: A class of which only a single instance can exist
The composition of classes and objects is central to many design principles Inheritance is used by structural class-creation patterns to create interfaces Structured object-patterns specify how to combine different objects to create new functions (sourcemaking, n.d.)
● Adapter: Match interfaces of different classes
● Bridge: Separates an object’s interface from its implementation
● Composite: A tree structure of simple and composite objects
● Decorator: Add responsibilities to objects dynamically
● Facade: A single class that represents an entire subsystem
● Flyweight: A fine-grained instance used for efficient sharing
● Private Class Data: Restricts accessor/mutator access
● Proxy: An object representing another object
The communication between Class objects is at the heart of these design patterns The patterns that are primarily concerned with communication between objects are known as behavioral patterns (sourcemaking, n.d.)
● Chain of responsibility: A way of passing a request between a chain of objects
● Command: Encapsulate a command request as an object
● Interpreter: A way to include language elements in a program
● Iterator: Sequentially access the elements of a collection
● Mediator: Defines simplified communication between classes
● Memento: Capture and restore an object's internal state
● Null Object: Designed to act as a default value of an object
● Observer: A way of notifying change to a number of classes
● State: Alter an object's behavior when its state changes
● Strategy: Encapsulates an algorithm inside a class
● Template method: Defer the exact steps of an algorithm to a subclass
● Visitor: Defines a new operation to a class without change
The Factory Method Pattern is a design pattern in object-oriented programming that provides a way to create objects It falls under the category of creational patterns, which focus on the process of object creation The core idea of the Factory Method is to allow for the creation of objects without specifying the exact class of the object that will be created (guru, 2020)
The problem that the Factory Method Pattern aims to solve can be understood through a common scenario in software development:
Direct Object Creation Issues: Imagine you are developing a software application where various parts of your code need to create objects of a class Typically, you might directly instantiate objects using the new keyword However, this approach has several drawbacks:
Tight Coupling: Your code becomes tightly coupled with the specific classes of the objects it creates This makes it hard to change or extend the code later, as changes to the object's class might require changes to every part of the code that uses it Lack of Flexibility: If you need to change the object's type or the process of its creation (like adding additional setup steps), you have to modify all the places in your code where the object is created
Complex Object Creation: In many cases, the process of creating an object can be complex, involving more than just a simple constructor call Managing this complexity directly in the client code can make the code less readable and harder to maintain (guru, 2020)
The Factory Method Pattern offers a solution to these problems by defining an interface for creating an object, but letting subclasses decide which class to instantiate Here’s how it addresses the aforementioned issues:
Encapsulate Object Creation: Instead of directly creating objects using the new keyword, the Factory Method encapsulates the object creation process in a separate method This method can be either in the same class or in a separate factory class Subclassing for Object Creation: The actual instantiation of the objects is done by subclasses that implement the factory method to create objects of different types This makes the client code independent of the concrete classes that are instantiated, allowing for more flexibility
Flexibility and Extensibility: If at some point you need to introduce a new object type or change the object creation process, you only need to introduce or modify a subclass The rest of your code does not need to change, as it only interacts with the factory method
Usage Example: Consider a logistics management application where you need to create different types of transport vehicles like trucks and ships Instead of directly instantiating these in your code, you use a factory method This method can be overridden in subclasses to create the specific type of vehicle required, thus separating the vehicle creation process from its usage in the application
In practical terms, the Factory Method Pattern provides a way to delegate the instantiation logic to subclasses, promoting loose coupling and making the code more modular, easier to extend, and easier to maintain It's particularly useful when the creation process is complex or when there needs to be flexibility in terms of the types of objects created (guru, 2020)
Abstract Factory is a creational design pattern that lets you produce families of related objects without specifying their concrete classes
When developing a cross-platform application, the task of managing and developing user interfaces across different operating systems, comes with a big formula Each platform requires different design and interface elements for the best user experience However, maintaining the same code base and supporting new platforms at the same time is a complex issue
To solve this problem, we can use the Abstract Factory Method design pattern This way, we can create a system of platform- specific Factories, each of which provides corresponding user interface objects (e.g Button, TextBox, Dialog)
Each specific Factory ensures that the generated object conforms to the look and feel appropriate for that particular platform This helps decouple application logic from platform-specific implementation details
When we want to add support for a new platform, we can simply deploy a new Factory without having to change the main source code of the application This helps reduce dependencies between components and makes application scaling easier
=> Abstract Factory Method is a flexible and extensible solution for managing and deploying user interfaces in cross-platform applications, reducing complexity and increasing code flexibility
Figure 16: Abstract Factory structure image (guru, n.d.)
Key Components in the Model:
- Abstract Products: declare interfaces for a set of distinct but related products which make up a product family
- Concrete Products: are various implementations of abstract products, grouped by variants Each abstract product (chair/sofa) must be implemented in all given variants (Victorian/Modern)
- The Abstract Factory: interface declares a set of methods for creating each of the abstract products
- Concrete Factories: implement creation methods of the abstract factory Each concrete factory corresponds to a specific variant of products and creates only those product variants
Design Pattern vs OOP
Object-oriented software development is a methodology where the software's structure revolves around objects that interact with each other to accomplish a goal These objects engage in communication, with one object often responding to messages Rather than focusing primarily on the logic necessary for managing these objects, object-oriented programming (OOP) places greater emphasis on the objects themselves This approach is particularly well-suited for large, intricate projects that require frequent updates or maintenance
In your everyday tasks, you can observe this object-oriented approach For example, when you go to the store, you interact with a car object An automobile consists of various components working together to transport you to your destination You insert the key object and turn the ignition object Through communication with the ignition object (via an electrical signal), it collaborates with the engine object to start the car
A design pattern is a proven solution to common programming problems While not exclusively related to Object-Oriented programming, most solutions are associated with OOP, although some can be applied to other paradigms as well While occasionally you might come up with brilliant ideas, most of the time, you won't To code effectively from the outset, you often need substantial experience Learning about Design Patterns is akin to acquiring knowledge from experienced individuals who have been constructing things for decades They have distilled their most commonly used solutions into straightforward, easy-to-understand concepts with memorable names You can choose to embrace this knowledge and benefit from it, or disregard it and potentially repeat their mistakes As demonstrated in the scenarios mentioned earlier, applying the appropriate design pattern to problem-solving is highly effective Thanks to the sample diagrams provided earlier, we were able to create a specific diagram for the given problem This expeditious and convenient approach significantly saves time and manpower in system planning work
Programming on a large scale is essential for modernizing human life Learning how to code enhances individuals' logical thinking and problem-solving abilities Programming also fosters creativity, leading to the development of numerous innovative products and applications Significantly, it requires extensive programming efforts to produce functional software that enhances and streamlines people's lives and work With the rapid advancement of information technology, developers have created an abundance of software and applications, resulting in increased economic and human productivity due to the time saved During their work on exercise 1, the writers gained valuable insights into various aspects, including Object-
Oriented Programming (OOP), UML diagrams, and design patterns The team engaged in discussions about fundamental OOP concepts such as inheritance, polymorphism, abstraction, and encapsulation, as well as the concepts of objects and classes They presented a scenario and depicted its UML representation in a diagram Subsequently, in the following section, the team explored Creational patterns like the Factory method, Structural patterns such as Facades, and Behavioral patterns like
Strategy In the future, the team intends to delve deeper into OOP applications and create new design patterns, along with generating UML diagrams for their project
References authoranuupadhyay, 2022 SOLID Principle in Programming: Understand With Real Life Examples [Online] Available at: https://www.geeksforgeeks.org/solid-principle-in-programming-understand-with-real-life-examples/ [Accessed 8 December 2023]. geeksforgeeks, 2023 Introduction of Object Oriented Programming [Online]
Available at: https://www.geeksforgeeks.org/introduction-of-object-oriented-programming/
[Accessed 07 12 2023] guru, 2018 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/mediator guru, 2018 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/observer guru, 2019 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/iterator guru, 2020 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/factory-method guru, 2020 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/singleton guru, 2020 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/adapter guru, 2020 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/facade guru, 2020 refactoring.guru [Online]
Available at: https://refactoring.guru/design-patterns/memento guru, n.d Behavioral Design Patterns [Online]
Available at: https://refactoring.guru/design-patterns/behavioral-patterns
[Accessed 8 December 2023] guru, n.d Creational Design Patterns [Online]
Available at: https://refactoring.guru/design-patterns/creational-patterns
[Accessed 8 December 2023] guru, n.d Decorator [Online]
Available at: https://refactoring.guru/design-patterns/decorator
[Accessed 8 December 2023] guru, n.d Structural Design Patterns [Online]
Available at: https://refactoring.guru/design-patterns/structural-patterns
Available at: https://raygun.com/blog/oop-concepts- java/#:~:textstraction%2C%20encapsulation%2C%20polymorphism%2C%20and,principles%20of%20object%2Doriented%20programming refactoring, 2018 Builder [Online]
Available at: https://refactoring.guru/design-patterns/builder
Available at: https://refactoring.guru/design-patterns/decorator
Available at: https://refactoring.guru/design-patterns/proxy
Available at: https://refactoring.guru/design-patterns/strategy
[Accessed 08 12 2023] sourcemaking, n.d Design Patterns [Online]
Available at: https://sourcemaking.com/
[Accessed 8 December 2023] guru (2020, 3 21) refactoring.guru Retrieved from refactoring.guru: https://refactoring.guru/design-patterns/bridge guru (2020, 3 21) refactoring.guru Retrieved from refactoring.guru: https://refactoring.guru/design-patterns/abstract-factory guru (2020, 3 21) refactoring.guru Retrieved from refactoring.guru: https://refactoring.guru/design-patterns/state guru (2020, 3 21) refactoring.guru Retrieved from refactoring.guru: https://refactoring.guru/design-patterns/visitor
Powered by TCPDF (www.tcpdf.org)