Professional Documents
Culture Documents
TP053217
UC1F2108SE
Q1
)A
Essentially, they're all the same. In order to specify the structure of your code, such as how
your class is organized to meet a requirement or solve an issue, you may use structural
design patterns. In contrast to Creational and Behavioral patterns, which demonstrate how
to make objects of a class communicate with one other, Design patterns explain how to
.make the objects of a class interact with each other
Similar to the adapter design, where one service "wraps" another, the decorator pattern
does the same thing. Decorators, on the other hand, disclose the service they're
embellishing, unlike adapters. Decorating an item is adding new features without altering
.the original thing's appearance
Adapter Pattern:
Translate between two different user interfaces Creating a web API for a client that
consumes another API that doesn't meet the client's expectations is an example of this. An
.adapter API is what you're looking for
Adapter
Decorator Pattern:
Features/behaviors are added that were previously unavailable. There are several examples
of how this may be done. For example, you can inherit from CountBankAccount and add the
Withdraw Count property to retrieve the total number of withdrawals for a given bank
account. This is a Decorator class that adds a non-existent functionality to
CountBankAccount called counting withdrawal operations. As an alternative, you can utilize
".the decorated class's object inside the decorator class, a technique called "composition
Decorator
)B
Q2
)A
)B
1. Class Inheritance
2. Protocol Extension
3. Decorator Pattern
An overview of the Open/Closed Principle is in order, so let's get started. "Software entities
(classes, modules, functions, etc.) should be open for expansion, but closed for modification"
.is a guideline for object-oriented design initially proposed by Bertrand Meyer
Class Inheritance
Initially, I thought it sounded like something out of a college classroom. This means that we
should write code that doesn't have to be rewritten whenever the requirements change.
Depending on the situation, such as the programming language, we may have to adapt our
approach. This example shows how inheritance and polymorphism may be used in Java, C#,
.or any other statically typed language
For example, creating a base class for rectangles and circles that offers an abstract method
.for computing their area is one way to solve this challenge
Inheriting from Shape the Rectangle and Circle classes now looks like this:
;return Width*Height
}
}
;return Radius*Radius*Math.PI
}
}
The AreaCalculator's Area method is now more easier and more robust since it can take any
.sort of Shape that we throw at it, making it more flexible
;double area = 0
;)(area += shape.Area
;return area
}
Decorator Pattern
The Decorator Pattern, which functions as a wrapper around our current entity and
allows us to implement the new attributes and methods within it, is the most
effective means of solving our problem. The same interface as the underlying thing
may be provided, and we can pass calls through to it. Here is an example of an
implementation that uses a static instantiation:
protocol Thing {
init()
protocol Sized {
init(size: Size) {
self.size = size
}
print(staticThingy)
Using the protocol "Thing," we may declare our interface and then comply to that interface
in our entity "Thingy" (line 9). Take note of the fact that the protocol has an initializer (line 3)
and that the name variable in our entity has a default value of "Thingy" (line 11). This is
because we want to statically pass in the type when we initialize our decorator (line 52) and
have it initialize itself, effectively turning it into the underlying entity in our decorator (line
34). It is possible to utilize a calculated property (line 25–32) to access the name property
within our underlying object while still providing a standard interface for our client. For our
decorator to have our new property "size," we first need to build a protocol named "Sized"
(line 15), and then we need to have our decorator adhere to that protocol (line 21).
Protocol Extension
Let’s say that I want my “Thingy” to be able to wobble (don’t ask me why…). My first
struc
t
Thing
y {
This clearly violates our Open-Closed Principle, which we have established. A possible
solution would be to build a protocol that declares the function and then incorporate its
:implementation into an extension of our struct
struct
Thingy
{
protocol Wobbleable {
func wobble()
func wobble() {
print("look at me
wobble")
}
print(thing.wobble())
In our prior examples, how did we go awry? Our initial attempt at implementing the Area
was clearly limited in scope. The question is whether or not it should have been. If I had to
guess, I'd say that context is everything. Because of our strong assumptions that the
customer will need additional shapes, we could have probably planned for this from the
start... Because my psychic powers haven't yet emerged, it's not always a good idea to try to
predict the needs of a project in advance, as this may easily lead to too complicated designs.
It's better to focus on developing code that is adequately written so that it may be easily
.modified if the needs change