You are on page 1of 11

Yosef Yahya Khalil

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

It is an object that implements the LayoutManager interface* and is responsible for


determining the size and location of the components within a container. Despite the fact
that components might give size and alignment clues, the layout manager of a container has
.the last word on the size and position of the components included within the container
Generally speaking, JPanels and content panes are the only containers about which you
need to be concerned with their layout managers. Unless you indicate otherwise when
establishing the JPanel object, each JPanel object is created to utilize a FlowLayout as its
default layout. BorderLayout is the default layout for content panes. Alternatively, if you do
not like the default layout manager that a panel or content pane employs, you have the
option of changing it to another layout manager. If you are not using JToolBar, the
FlowLayout and BorderLayout managers will only be used for prototyping unless you are
utilizing JToolBar. In order to run any genuine program, the layout manager must be reset.
Again, rather than writing the manager by hand, you should make use of a suitable tool to
.accomplish this

)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

public abstract class Shape

;)(public abstract double Area

Inheriting from Shape the Rectangle and Circle classes now looks like this:

public class Rectangle : Shape

public double Width { get; set; }

public double Height { get; set; }

)(public override double Area

;return Width*Height

}
}

public class Circle : Shape


{

public double Radius { get; set; }

)(public override double Area

;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

public double Area(Shape[] shapes)

;double area = 0

foreach (var shape in shapes)

;)(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()

var name: String { get set }

struct Thingy : Thing {

var name: String = "Thingy"

protocol Sized {

var size: Size { get set }

struct StaticSizedThingy<T: Thing> : Sized {

var size: Size

var name: String {


get {
return _thingy.name
}
set {
_thingy.name = newValue
}
}

private var _thingy: T = T()

init(size: Size) {
self.size = size
}

extension StaticSizedThingy : CustomStringConvertible {

var description: String {


return "I am a statically construcuted thingy called \(name), and I
am \(size) sized"
}

let staticThingy = StaticSizedThingy<Thingy>(size: .small)

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

instinct might be to do this:

struc
t
Thing
y {

var name: String

func wobble() {} //hmmm.


}

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
{

var name: String

protocol Wobbleable {

func wobble()

extension Thingy : Wobbleable {

func wobble() {
print("look at me
wobble")
}

let thing = Thingy(name: "Bob")

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

You might also like