Design Patterns by Tutorials Flashcards Preview

iOS > Design Patterns by Tutorials > Flashcards

Flashcards in Design Patterns by Tutorials Deck (108)
Loading flashcards...
1
Q

Notification message flow

A
2
Q

What are design pattens?

A

* Design patterns aren’t concrete implementations, but rather, they are a starting point for writing code.

* Design patterns collectively form a set of best practices to help you write more understandable and easier-to-maintain code.

3
Q

UML

A

Unified Modeling Language

4
Q

“inherits from,” and it is read as “is a” in UML terms

A
5
Q

indicate a property, which is known as an /association/in UML terms.

“has a.”

A
6
Q

“Conforms to” or “Implements protocol”

A
7
Q

Indicate “uses,” which is called a “dependency” in UML terms

A

* A weak property or delegate.
* An object that’s passed into a method as a parameter, but not held as a property.
* A loose coupling or callback, such as an IBAction from a view to a controller.

8
Q

How you’d indicate that Dog delegates to a PetOwning object

A
9
Q

How to indicate parameters and methods in UML?

A
10
Q

MVC diagram

A

Controllers are allowed to have strong properties for their model and view so they can
be accessed directly. Controllers may have more than one model and/or view.

Conversely, models and views should nothold a strong reference to their owning controller. This would cause a retain cycle.

11
Q

Models in MVC

A

Models hold onto application data. They are usually structs or simple classes.

12
Q

Views in MVC

A

Views display visual elements and controls on screen. They are usually subclasses of UIView.

13
Q

Controllers in MVC

A

Controllers coordinate between models and views. They are usually subclasses of UIViewController.

14
Q

What references views and models should have in MVC?

A

Models and views should not hold a strong reference to their owning controller. This would cause a retain cycle.

Views may have a weak reference to their owning controller through a delegate. For example, a UITableView may hold a weak reference to its owning view controller for its delegate and/or dataSource references. However, the table view doesn’t /know/these are set to its owning controller - they just happen to be.

15
Q

What references VC have in MVC?

A

Controllers are allowed to have strong properties for their model and view so they can
be accessed directly. Controllers may have more than one model and/or view.

16
Q

What should you be careful about in MVC?

A

have a lot of logic in the controllers

Not every object will neatly fit into the category of model, view or controller.

17
Q

What level asses control you should choose?

A

you’ll use public for types, properties and methods that should be publicly accessible to other classes;

you’ll use private if something should only be accessible to the type itself

you’ll use internal if it should be accessible to subclasses or related classes but isn’t intended for general use otherwise

18
Q

How correctly set main view of view controller while you keep this view and outlets somewhere else?

A

public var mainView: MainView! {
guard isViewLoaded else { return nil }
return (view as! MainView)
}

You keep outlets in MainView class that inherit from UIView

19
Q

Show delegation pattern diagram and explain each part of diagram

A

The delegation pattern has three parts: an object needing a delegate, a delegate protocol and a delegate.

An object needing a delegate, also known as the delegating object.It’s the object that /has/a delegate. The delegate is usually held as a weak property to avoid a retain cycle where the delegating object retains the delegate, which retains the delegating object.

A delegate protocol, which defines the methods a delegate may or should implement.

A delegate, which is the helper object that implements the delegate protocol.

20
Q

When should you use a delegation pattern?

A

Use this pattern to break up large classes or create generic, reusable components.

The delegation pattern allows an object to use a helper object to perform a task, instead of doing the task itself.

This allows for code reuse through object composition, instead of inheritance.

21
Q

What DataSource- and Delegate-named objects delegate pattern follow?

A

They follow the delegation pattern, as each involves one object asking another to provide data or do something.

22
Q

Apple frameworks commonly use the term DataSource for what?

A

to group delegate methods that /provide/data. For example, UITableViewDataSource is expected to provide UITableViewCells to display.

23
Q

if dataSource and delegate to be set to the /same/ object?

A

they don’t have to be, and it can be very beneficial at times to have them set to different objects.

24
Q

The common convention in iOS to set delegate objects?

A

/after/an object is created

25
Q

It’s common convention in delegate pattern

A

It’s common convention to pass the delegating object.

This way, the delegate can use or inspect the caller if needed.

26
Q

What should you be careful about in delegation pattern?

A

they can be overused. Be careful about creating /too many/delegates for an object.
If an object needs several delegates, this may be an indicator that it’s doing too much. Consider breaking up the object’s functionality for specific use cases, instead of one catch-all class.

f you find yourself constantly switching between classes to understand what’s happening, then that’s a sign you have too many. Similarly, if you cannot understand why a certain delegate is useful, then that’s a sign it’s too small, and you’ve split things up too much.

be careful about creating retain cycles - Delegates should be weak properties in the vast majority of use cases

27
Q

What delegation pattern allows you to do?

A

allows you to break up large classes and create generic, reusable components.

28
Q

Strategy Pattern diagram and explain each part

A

The object using a strategy*. This is most often a view controller when the pattern is used in iOS app development, but it can technically be any kind of object that needs interchangeable behavior.

The strategy protocol*defines methods that every strategy must implement.

The strategies*are objects that conform to the strategy protocol.

29
Q

What strategy patten defines?

A

The strategy pattern defines a family of interchangeable objects.

30
Q

What strategy pattern makes to app?

A

Makes apps more flexible and adaptable to changes at runtime, instead of requiring compile-time changes.

31
Q

When should you use strategy pattern?

A

Use the strategy pattern when you have two or more different behaviors that are interchangeable.

This pattern is similar to the delegation pattern: both patterns rely on a protocol instead of concrete objects for increased flexibility. Consequently, /any/object that implements the strategy protocol can be used as a strategy at runtime.

Unlike delegation, the strategy pattern uses a /family/of objects.

Delegates are often fixed at runtime. For example, the dataSource and delegate for a UITableView can be set from Interface Builder, and it’s rare for these to change during runtime.

Strategies, however, are intended to be easily interchangeable at runtime.

32
Q

Strategy vs Delegation pattern?

A

Delegates are often fixed at runtime. For example, the dataSource and delegate for a UITableView can be set from Interface Builder, and it’s rare for these to change during runtime.

Strategies, however, are intended to be easily interchangeable at runtime.

This pattern is similar to the delegation pattern: both patterns rely on a protocol instead of concrete objects for increased flexibility. Consequently, /any/object that implements the strategy protocol can be used as a strategy at runtime.

Unlike delegation, the strategy pattern uses a /family/of objects.

Both patterns use a protocol for flexibility. Unlike the delegation pattern, however, strategies are /meant/to be switched at runtime, whereas delegates are usually fixed.

33
Q

What should you be careful about using strategy pattern?

A

Be careful about overusing this pattern. In particular, if a behavior /won’t/ever change, it’s okay to put this directly within the consuming view controller or object context. The trick to this pattern is knowing /when/to pull out behaviors, and it’s okay to do this lazily as you determine where it’s needed.

34
Q

What strategy pattern defines?

A

defines a family of interchangeable objects that can be set or switched at runtime.

35
Q

Singleton vs Singleton Plus

A

The singleton pattern restricts a class to have only /one/ instance.

The “singleton plus” pattern is also common, which provides a “shared” singleton instance, but it also allows other instances to be created too.

\* The singleton pattern restricts a class to only one instance. 
\* The singleton plus pattern provides a "default" shared instance but also allows other instances to be created too.
36
Q

When should you use singleton pattern?

A

Use the singleton pattern when having more than one instance of a class would cause problems, or when it just wouldn’t be logical.

37
Q

What should you be careful about when using singleton pattern?

A

A very most common reason why singletons are problematic is testing. If you have state being stored in a global object like a singleton then order of tests can matter, and it can be painful to mock them. Both of these reasons make testing a pain.
Lastly, beware of “code smell” indicating your use case isn’t appropriate as a singleton at all. For example, if you often need many custom instances, your use case may be better as a regular object.

Be careful about overusing this pattern! Before you create a singleton, consider other ways to solve the problem without it. If a singleton really is best, prefer to use a singleton plus over a singleton.

38
Q

If you encounter a situation where you’re tempted to use a singleton,

A

first consider other ways to accomplish your task. Instead, consider passing models via an initializer or property.
If you determine you actually /do/need a singleton, consider whether a singleton plus makes more sense.

39
Q

When you decided to use singleton - what to ask yourself and what they determine?

A

Will having more than one instance cause problems? Will it ever be useful to have custom instances? Your answers will determine whether its better for you to use a true singleton or singleton plus

40
Q

Memento pattern diagram and explaining

A

and explaining

  1. The originator is the object to be saved or restored.
  2. The memento represents a stored state.
  3. The caretaker requests a save from the originator and receives a memento in response. The caretaker is responsible for persisting the memento and, later on, providing the memento back to the originator to restore the originator’s state.

The originator is the object to be saved; the memento is a saved state; and the caretaker handles, persists and retrieves mementos.

41
Q

When should you use memento pattern?

A

Use the memento pattern whenever you want to save and later restore an object’s state.

42
Q

What should you be careful about when using memento pattern?

A

Be careful when adding or removing Codable properties: both encoding and decoding can throw an error. If you force unwrap these calls using try! and you’re missing any required data, your app will crash!

To mitigate this problem, avoid using try! unless you’re /absolutely/ sure the operation will succeed. You should also plan ahead when changing your models.

43
Q

What iOS provides for memento pattern?

A

iOS provides Encoder for encoding a memento to, and Decoder for decoding from, a memento. This allows encoding and decoding logic to be used across originators.

44
Q

Observer pattern diagram

A

The observer pattern allows “observer” objects to register for and receive updates whenever changes are made to “subject” objects.

This pattern allows us to define “one-to-many” relationships between many observers receiving updates from the same subject.

This pattern involves two main objects:

  1. The subject is the object that’s being observed.
  2. The observer When should you use itis the object doing the observing.
45
Q

When should you use observer pattern?

A

Use the observer pattern whenever you want to receive changes made on another object.

This pattern is often used with MVC, where the view controller is the observer and the model is the subject. This allows the model to communicate changes back to the view controller /without/needing to know anything about the view controller’s type. Thereby, different view controllers can use and observe changes on a shared model type.

46
Q

How looks like KVO with NSObject?

A
@objcMembers public class KVOSubjectUser: NSObject {
// 2
dynamic var name: String
// 3
public init(name: String) {
self.name = name
}
}
let kvoUser = KVOSubjectUser(name: "Ray")
var kvoObserver: NSKeyValueObservation? =
kvoUser.observe(\.name, options: [.initial, .new]) {
(user, change) in
print("User's name is \(user.name)")
}

A fantastic feature of using KVO in Swift is that you /don’t/have to explicitly remove KVO observers or closures. Instead, observers are weakly referenced, and their related closures are automatically removed whenever an observer becomes nil

47
Q

downside of KVO with NSObject

A

You’re required to subclass NSObject and use the Objective-C runtime

48
Q

Observable wrapper

A

You can created your very own Observable wrapper, which doesn’t depend on /any/ Apple frameworks or the Objective-C runtime. Code is in book.

49
Q

What should you be careful about with using observer pattern?

A

For simple models or properties that /never/change, the observer pattern may be overkill; it can lead to unnecessary work.
Before you implement the observer pattern, define /what/you expect to change and under which conditions. If you can’t identify a reason for an object or property to change, you’re likely better off /not/implementing KVO/Observable immediately for it.

A unique identifier, for example, isn’t useful as an observable property since by definition it should never change.

50
Q

Two ways of using observer pattern?

A

* One way to implement the observer pattern is using KVO. However, this /requires/you to subclass NSObject, which isn’t always desirable.

* Another way to implement the observer pattern is using an Observable wrapper class. This isn’t provided by Swift, so you must write your own. However, it doesn’t require you to depend on NSObject, Foundation or any other frameworks.

51
Q

Builder Pattern diagram and explanation

A

The builder pattern allows complex objects to be created step-by-step instead of all-at-once via a large initializer.

  1. The director accepts inputs and coordinates with the builder. This is usually a view controller or a helper class that’s used by a view controller.
  2. The product is the complex object to be created. This can be either a struct or a class, depending on desired reference semantics. It’s usually a model, but it can be any type depending on your use case.
  3. The builder accepts step-by-step inputs and handles the creation of the product. This is often a class, so it can be reused by reference.

* The director accepts inputs and coordinates with the builder; the product is the complex object that’s created; and the builder takes step-by-step inputs and creates the product.

52
Q

When should you use builder pattern?

A

Use the builder pattern when you want to create a complex object using a series of steps.

This pattern works especially well when a product requires /multiple inputs/. The builder abstracts how these inputs are used to create the product, and it accepts them in whatever order the director wants to provide them.

53
Q

What should you be careful about when using builder pattern?

A

The builder pattern works best for creating complex products that require multiple inputs using a series of steps. If your product doesn’t have several inputs or can’t be created step by step, the builder pattern may be more trouble than it’s worth.

Instead, consider providing convenience initializers to create the product.

54
Q

what is view model?

A

View models are classes that take objects and transform them into different objects, which can be passed into the view controller and displayed on the view. They’re especially useful for converting computed properties such as Date or Decimal into a String or something else that actually can be shown in a UILabel or UIView.

55
Q

view model - one view
view model - many views
where to configure view?

A

If you’re only using the view model with one view, it can be good to put all the configurations into the view model. However, if you’re using more than one view, you might find that putting all the logic in the view model clutters it. Having the configure code separated into each view may be simpler.

56
Q

When you should use Factory pattern?

A

Use the factory pattern whenever you want to separate out product creation logic, instead of having consumers create products directly.

A factory is very useful when you have a group of related products, such as polymorphic subclasses or several objects that implement the same protocol. For example, you can use a factory to inspect a network response and turn it into a concrete model subtype.

57
Q

Factory diagram

A
58
Q

A factory is most useful if you have

A

a group of related products, or if you cannot create an object until more information is supplied (such as completing a network call, or waiting on user input).

59
Q

A factory’s goal is

A

isolate object creation logic within its own construct.

60
Q

The factory method adds a layer

A

of abstraction to create objects, which reduces duplicate code.

61
Q

Adapter diagram

A
62
Q

When should you use Adapter Pattern?

A

Classes, modules, and functions can’t always be modified, especially if they’re from a third-party library. Sometimes you have to adapt instead!
You can create an adapter either by extending an existing class, or creating a new adapter class.

connecting two elements that otherwise won’t “fit” with each other.

plan ahead for future changes.

63
Q

What should you be careful about in Adapter Pattern?

A

Remember not to jump to the adapter pattern unless you recognize there’s a possibility for change. It’s always preferable to have classes that can easily work together, but there will often be situations where classes need to be connected by an adapter.

64
Q

The adapter pattern allows you

A

to reuse a class even if it lacks required components or has incompatible components with required objects.

65
Q

Adapter key points

A
  • The adapter pattern is useful when working with classes from third party libraries that cannot be modified. You can use protocols to have them work with project’s custom classes.
  • To use an adapter, you can either extend the legacy object, or make a new adapter class.
  • The adapter pattern allows you to reuse a class even if it lacks required components or has incompatible components with required objects.
  • plan ahead for future changes.
66
Q

Iterator diagram

A

The iterator pattern provides a standard way to loop through a collection using a for
in syntax.

67
Q

When should you use Iterator pattern?

A

Use the iterator pattern when you have a class or struct that holds a group of ordered objects, and you want to make it iterable using a for in loop.

68
Q

What should you be careful about Iterator Pattern?

A

There is a protocol named IteratorProtocol, which allows you to customize how your object is iterated. You simply implement a next() method that returns the next object in the iteration. However, you’ll probably never need to conform to IteratorProtocol directly.
Even if you need a custom iterator, it’s almost always better to conform to Sequence and provide custom next() logic, instead of conforming to IteratorProtocol directly.

69
Q

When you want to iterate through custom objects it’s better to

A

conform to Sequence, instead of
IteratorProtocol directly.

By conforming to Sequence, you will get higher-order functions like map and filter
for free.

70
Q

Prototype diagram

A

“The key to creating a Copying protocol is creating a copy initializer with the form init(_ prototype:).”

71
Q

When you should use prototype pattern?

A

“Use this pattern to enable an object to copy itself.
For example, Foundation defines the NSCopying protocol. However, this protocol was designed for Objective-C, and unfortunately, it doesn’t work that well in Swift. You can still use it, but you’ll wind up writing more boilerplate code yourself.”

72
Q

shallow vs deep copy

A

“A shallow copy creates a new object instance, but doesn’t copy its properties. Any properties that are reference types still point to the same original objects. For example, whenever you copy a Swift Array, which is a struct and thereby happens automatically on assignment, a new array instance is created but its elements aren’t duplicated.

A deep copy creates a new object instance and duplicates each property as well. For example, if you deep copy an Array, each of its elements are copied too. Swift doesn’t provide a deep copy method on Array by default

73
Q

“What should you be careful about in prototype pattern?”

A
"As shown in the playground example, by default it's possible to pass a superclass instance to a subclass's copy initializer. This may not be a problem if a subclass can be fully initialized from a superclass instance. However, if the subclass adds any new properties, it may not be possible to initialize it from a superclass instance.
To mitigate this issue, you can mark the subclass copy initializer as "unavailable." In response, the compiler will refuse to compile any direct calls to this method.
It's still possible to call the method indirectly, like copy() does. However, this safeguard should be "good enough" for most use cases.
If this doesn't prevent issues for your use case, you'll need to consider how exactly you want to handle it. For example, you may print an error message to the console and crash, or you may handle it by providing default values instead."
74
Q

What prototype pattern enables and what it involves?

A

“The prototype pattern enables an object to copy itself. It involves two types: a copying protocol and a prototype.”

75
Q

State Pattern Diagram

A

The context is the object that has a current state and whose behavior changes.

The state protocol defines required methods and properties. Developers commonly substitute a base state class in place of a protocol. By doing so, they can define stored properties in the base, which isn't possible using a protocol.
Even if a base class is used, it's not intended to be instantiated directly. Rather, it's defined for the sole purpose of being subclassed. In other languages, this would be an abstract class. Swift currently doesn't have abstract classes, however, so this class isn't instantiated by convention only.

Concrete states conform to the state protocol, or if a base class is used instead, they subclass the base. The context holds onto its current state, but it doesn’t know its concrete state type. Instead, the context changes behavior using polymorphism: concrete states define how the context should act. If you ever need a new behavior, you define a new concrete state.

76
Q

“where do you actually put the code to change the context’s current state? Within the context itself, the concrete states, or somewhere else?”

A

You may be surprised to find out that the state pattern doesn’t tell you where to put state change logic! Instead, you’re responsible for deciding this. This is both a strength and weakness of this pattern: It permits designs to be flexible, but at the same time, it doesn’t provide complete guidance on how to implement this pattern.”

77
Q

When you should use state pattern?

A

use the state pattern to create a system that has two or more states that is changes between during the lifetime

78
Q

Multicast delegate pattern diagram

A

An object needing a delegate, also known as the delegating object, is the object

that has one or more delegates.

The delegate protocol defines the methods a delegate may or should implement.

The delegate(s) are objects that implement the delegate protocol.

The multicast delegate is a helper class that holds onto delegates and allows you to notify each delegate whenever a delegate-worthy event happens

79
Q

The main difference between the multicast delegate pattern and the delegate pattern is

A

the presence of a multicast delegate helper class. Swift doesn’t provide you this class by default. However, you can easily create your own, which you’ll do in this chapter.

80
Q

When should you use multicast delegate?

A

Use this pattern to create one-to-many delegate relationships.
For example, you can use this pattern to inform multiple objects whenever a change has happened to another object. Each delegate can then update its own state or perform relevant actions in response.

81
Q

What should you be careful about when you use multicast delegate?

A

This pattern works best for “information only” delegate calls.
If delegates need to provide data, this pattern doesn’t work well. That’s because multiple delegates would be asked to provide the data, which could result in duplicated information or wasted processing.

82
Q

The multicast delegate pattern allows you to create one-to-many delegate relationships. It involves four types:
[explain each type]

A

an object needing a delegate, a delegate protocol, delegates, and a multicast delegate.

An object needing a delegate has one or more delegates; the delegate protocol defines the methods a delegate should implement; the delegates implement the delegate protocol; and the multicast delegate is a helper class for holding onto and notifying the delegates.

83
Q

Facade diagram and explanation

A

The facade provides simple methods to interact with the system. This allows consumers to use the facade instead of knowing about and interacting with multiple classes in the system.

The dependencies are objects owned by the facade. Each dependency performs a small part of a complex task.

The facade provides simple methods to interact with the system. Behind the scenes, it owns and interacts with its dependencies, each of which performs a small part of a complex task.

84
Q

When should you use facade pattern?

A

Use this pattern whenever you have a system made up of multiple components and want to provide a simple way for users to perform complex tasks.

For example, a product ordering system involves several components: customers and
products, inventory in stock, shipping orders and others.

Instead of requiring the consumer to understand each of these components and how they interact, you can provide a facade to expose common tasks such as placing and fulfilling a new order.

85
Q

What should you be careful about facade pattern?

A
Be careful about creating a "god" facade that knows about every class in your app.
It's okay to create more than one facade for different use cases. For example, if you notice a facade has functionality that some classes use and other functionality that other classes use, consider splitting it into two or more facades.
86
Q

The facade pattern provides a simple interface to a complex system. It involves two types:

A

the facade and its dependencies.

87
Q

When should you use flyweight pattern?

A

Use a flyweight in places where you would use a singleton, but you need multiple shared instances with different configurations. If you have an object that’s resource intensive to create and you can’t minimize the cost of creation process, the best thing to do is create the object just once and pass it around instead.

88
Q

flyweight pattern diagram

A
89
Q

What should you be careful about using flyweight pattern?

A

In creating flyweights, be careful about how big your flyweight memory grows. If you’re storing several flyweights, as in colorStore above, you minimize memory usage for the same color, but you can still use too much memory in the flyweight store.

To mitigate this, set bounds on how much memory you use or register for memory warnings and respond by removing some flyweights from memory. You could use a LRU (Least Recently Used) cache to handle this.

Also be mindful that your flyweight shared instance must be a class and not a struct. Structs use copy semantics, so you don’t get the benefits of shared underlying data that comes with reference types.

90
Q

The most common things for flyweight

A

fonts & colors

91
Q

describe flyweight pattern

A

The flyweight pattern minimizes memory usage and processing.

This pattern has objects, called flyweights, and a static method to return them. It’s a variation on the singleton pattern.

When creating flyweights, be careful about the size of your flyweight memory. If you’re storing several flyweights, it’s still possible to use too much memory in the flyweight store.

Examples of flyweights include caching objects such as images, or keeping a pool of objects stored in memory for quick access.

92
Q

Mediator pattern

A

The mediator pattern is a behavioral design pattern that encapsulates how objects communicate with one another

93
Q

Mediator pattern diagram

A

The colleagues are the objects that want to communicate with each other. They implement the colleague protocol.

The colleague protocol defines methods and properties that each colleague must implement.

The mediator is the object that controls the communication of the colleagues. It implements the mediator protocol.

The mediator protocol defines methods and properties that the mediator must

implement.

Each colleague contains a reference to the mediator, via the mediator protocol. In lieu of interacting with other colleagues directly, each colleague communicates through the mediator.

94
Q

When should you use mediator protocol?

A

This mediator pattern is useful to separate interactions between colleagues into an object, the mediator.

This pattern is especially useful when you need one or more colleagues to act upon events initiated by another colleague, and, in turn, have this colleague generate further events that affect other colleagues.

95
Q

What should you be careful about mediator pattern?

A

This pattern is very useful in decoupling colleagues.

Instead of colleagues interacting directly, each colleague communicates through the mediator.

However, you need to be careful about turning the mediator into a “god” object — an object that knows about every other object within a system.

If your mediator gets too big, consider breaking it up into multiple mediator-colleague systems. Alternatively, consider other patterns to break up the mediator, such as delegating some of its functionality.

96
Q

Key Points Mediator

A

The mediator pattern encapsulates how objects communicate with one another. It involves four types: colleagues, a colleague protocol, a mediator, and a mediator protocol.

The colleagues are the objects that communicate; the colleague protocol defines methods and properties all colleagues must have; the mediator controls the communication of the colleagues; and the mediator protocol defines required methods and properties that the mediator must have.

In lieu of talking directly, colleagues hold onto and communicate through the mediator. The colleague protocol and mediator protocol helps prevent tight coupling between all objects involved.

97
Q

The colleague protocol and mediator protocol helps prevent

A

tight coupling between all objects involved.

98
Q

Composite diagram

A

The composite pattern is a structural pattern that groups a set of objects into a tree structure so that they may be manipulated as though they were one object. It uses three types:

The component protocol ensures all constructs in the tree can be treated the same way.

A leaf is a component of the tree that does not have child elements.

A composite is a container that can hold leaf objects and composites.

99
Q

When should you use composite pattern?

A

If your app’s class hierarchy forms a branching pattern, trying to create two types of classes for branches and nodes can make it difficult for those classes to communicate.

You can solve this problem with the composite pattern by treating branches and nodes the same by making them conform them to a protocol. This adds a layer of abstraction to your models and ultimately reduces their complexity.

100
Q

What should you be careful about composite pattern?

A

Make sure your app has a branching structure before using the composite pattern. If you see that your objects have a lot of nearly identical code, conforming them to a protocol is a great idea, but not all situations involving protocols will require a composite object.

101
Q

Key Points Composite

A

The composite pattern is a structural pattern that groups a set of objects into a tree so that they may be manipulated as though they were one object.

If your app’s class hierarchy forms a branching pattern, you can treat branches and nodes as almost the same objects by conforming them to a component protocol. The protocol adds a layer of abstraction to your models, which reduces their complexity.

This is a great pattern to help simplify apps that have multiple classes with similar features. With it, you can reuse code more often and reduce complexity in your classes.

A file hierarchy is an everyday example of the composite pattern. All .mp3 and .jpeg files, as well as folders, share a lot of functions such as “open” and “move to trash.” You can move and store groups of different files, even if they aren’t all the same type, as they all conform to a component protocol.

102
Q

Command pattern diagram

A

The invoker stores and executes commands.

The command encapsulates the action as an object.

The receiver is the object that’s acted upon by the command.

103
Q

When should you use command pattern?

A

Use this pattern whenever you want to create actions that can be executed on receivers at a later point in time. For example, you can create and store commands to be performed by a computer AI, and then execute these over time.

104
Q

What should you be careful about in command pattern?

A

The command pattern can result in many command objects. Consequently, this can lead to code that’s harder to read and maintain. If you don’t need to perform actions later, you may be better off simply calling the receiver’s methods directly.

105
Q

Key points of command pattern

A

The command pattern encapsulates information to perform an action into a command object. It involves three types: an invoker, command and receiver.

The invoker stores and executes commands; the command encapsulates an action as an object; and the receiver is the object that’s acted upon.

This pattern works best for actions that need to be stored and executed later. If you always intend to execute actions immediately, consider calling the methods directly on the receiver instead.

106
Q

Chain-of-Responsibility Pattern

A

The client accepts and passes events to an instance of a handler protocol. Events may be simple, property-only structs or complex objects, such as intricate user actions.

The handler protocol defines required properties and methods that concrete handlers must implement. This may be substituted for an abstract, base class instead allowing for stored properties on it. Even then, it’s still not meant to be instantiated directly. Rather, it only defines requirements that concrete handlers must fulfill.

The first concrete handler implements the handler protocol, and it’s stored directly by the client. Upon receiving an event, it first attempts to handle it. If it’s not able to do so, it passes the event on to its next handler.

the client can treat all of the concrete handlers as if they were a single instance. Under the hood, each concrete handler determines whether or not to handle an event passed to it or pass it on to the next handler. This happens without the client needing to know anything about the process

107
Q

When should you use chain-of-responsibility pattern?

A

Use this pattern whenever you have a group of related objects that handle similar events but vary based on event type, attributes or anything else related to the event.

Concrete handlers may be different classes entirely or they may be the same class type but different instances and configurations.

108
Q

What should you be careful about chain-of-responsibility?

A

The chain-of-responsibility pattern works best for handlers that can determine very quickly whether or not to handle an event. Be careful about creating one or more handlers that are slow to pass an event to the next handler. You also need to consider what happens if an event can’t be handled. What if you return nil, throw an error or something else? You should identify this upfront, so you can plan your system appropriately.

You should also consider whether or not an event needs to be processed by more than one handler. As a variation on this pattern, you can forward the same event to all handlers, instead of stopping at the first one that can handle it, and return an array of response objects.