Design Patterns Flashcards
Two main philosophies behind design patterns ?
- Code reuse
- Flexibility
Name 5 creational design patterns
Singleton pattern
Builder pattern
Factory method pattern
Abstract factory pattern
Prototype pattern
What is the singleton pattern
Restricts the initialization of a class to a single instance for the lifetime of the application
Disadvantages of the singleton pattern
- Introduces global state
- Can introduce hidden dependencies and tight coupling
- Dealing with race conditions in multi-threaded apps
Advantages of the singleton pattern
Can share object without having to pass it in every method call (ex: store a Bluetooth connection in singleton to maintain connection across pages)
Code Example of Singleton Pattern
static variable
class MySingleton {
static let sharedInstance = MySingleton();
var myNumber = 0
private init() { }
}
What is the builder pattern ?
Initializing an instance of a type that requires a large number of configurable values
A separate “builder type” is used that contains information required to initialize the complex type.
Have multiple “builder types” to initialize each type
OR
Single builder type and then set options as needed
Code Example of Builder Pattern
protocol BurgerBuilder {
var name: String {get }
var patties: Int {get}
var bacon: Bool { get}
var cheese: Bool {get}
…
var tomato: Bool: {get}
}
struct HamburgerBuilder: BurgerBuilder {
let name = “Hamburger”
let patties = 1
let cheese = false;
…
let tomato = false
}
struct CheeseburgerBuilder {
let name = “Cheeseburger”
let patties = 1
let cheese = true
…
let tomato = false
}
struct Burger {
var name: String
var patties: Int
var cheese: Bool
…
var tomato: Bool
init(builder: BurgerBuilder_ {
self.name = builder.name
self.patties = builder.patties
…
}
var myCheeseburger = Burger(builder: CheeseburgerBuilder());
var holdKetchupCB = Burger(CheeseBurgerBuilder())
holdTheKetchupCB.ketchup = false
Alternate Code for Build Pattern
struct BurgerBuilder {
var name = “Burger”
var patties = 1
var cheese = false
…
}
mutating func setPatties(choice: Int) { self.patties = choice }
}
// Bacon Cheeseburger
var burgerBuilder = BurgerBuilder()
burgerBuilder.setCheese(choice: true)
burgerBuilder.setBacon(choice:true)
Name some structural design patterns
Bridge
Facade
Proxy
Adapter
Composite
Decorator
Flyweight
Describe the bridge pattern
Can be thought of as 2-layer abstraction
Taking interacting features and separating the functionality that is SPECIFIC to each feature from the SHARED functionality. a BRIDGE type encapsulates the shared functionality
Code example for the bridge pattern
protocol Message {
var messageString: String {get set}
init(messageString: String)
func prepareMessage()
}
protocol Sender {
sendMessage(message: Message)
}
// PlainTextMessage - prepareMessage is empty
// DESEncryptedMessage - prepareMessage does the encryption
// Advanced - Using a bridge
struct MessagingBridge {
static func sendMessage(message: Message, sender: Sender) {
var mySender = sender
message.PrepareMessage()
mySender.message = message
mySender.verifyMessage()
mySender.sendMessage()
}
Describe the facade pattern
Hide the complexity of the API behind a simple interface
CDP example - cameraCapture (CaptureCheck: sides = 2, source = camera, orient = landscape)
CaptureReceipt(sides = 1, source = camera OR photo roll, orient = portrait)
Describe the proxy pattern
There is one type acting as an interface for another type or API
Usually one of two uses:
layer of abstraction between a single API and my code
Need API changes but don’t have the code or there are dependencies on the API elsewhere in the code
Code example for the proxy design pattern
struct HouseProxy {
var house= House()
mutating func addStory(floorPlan: FloorPlan) -> Bool {
if house.stories.count <= 2 {
house.addStory(floorPlan: floorplan)
return true
} else {
return false
}
}
}
var ourHouse = HouseProxy()
// create floorplans for each level
ourHouse.addStory(floorPlan: basement)
ourHouse.addStory(floorPlan: firstStory)
ourHouse.addStory(floorPlan: secondStory)