Skip to content

Commit b97fa78

Browse files
Update README.md
1 parent cae5003 commit b97fa78

File tree

1 file changed

+289
-0
lines changed

1 file changed

+289
-0
lines changed

README.md

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,3 +2804,292 @@ Summary:
28042804

28052805
Strategy pattern allows us to define a set of related algorithms and allows client to choose any of the algorithms at runtime. It allows us to add new algorithm without modifying existing algorithms.
28062806

2807+
**19) Behavioral - Command Design Pattern:**
2808+
2809+
Definition:
2810+
2811+
The definition of Command provided in the original Gang of Four book on DesignPatterns states:
2812+
2813+
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
2814+
2815+
Command is a behavioral design pattern that decouples the object that invokes the operation from the object that knows how to perform it. It lets us turn requests into stand-alone objects by providing request objects with all the necessary information for the action to be taken.
2816+
Usage:
2817+
Let us consider a decision review system in a cricket match where the on-field umpire is not sure if a batsman is out or not. This umpire then asks the TV Umpire to check TV replays and make a decision. The TV umpire then commands the TV operator to show OUT/ NOT OUT on the screen present in the ground depending upon the decision made.
2818+
2819+
Let’s see how we can design such system with the help of Command design pattern.
2820+
2821+
```
2822+
import UIKit
2823+
import Foundation
2824+
2825+
protocol Command{
2826+
func execute()
2827+
}
2828+
2829+
We define a protocol named Command with a function named execute.
2830+
class ScreenDisplay{
2831+
private var showOutOnDisplay = false
2832+
2833+
func isBatsmanOut(){
2834+
showOutOnDisplay = true
2835+
print("Batsman is OUT")
2836+
}
2837+
2838+
func isBatsmanNotOut(){
2839+
showOutOnDisplay = false
2840+
print("Batsman is NOTOUT")
2841+
}
2842+
2843+
}
2844+
2845+
```
2846+
2847+
We then define a class called ScreenDisplay which is used to display the decision made by the TV umpire to public. It has a private variable named showOutOnDisplay which is initialised to false.
2848+
It has two methods defined. Based on the bool property, these methods show batsman OUT/ NOT OUT on the screen.
2849+
2850+
```
2851+
class BatsmanOutCommand : Command{
2852+
var screenDisplay : ScreenDisplay
2853+
2854+
init(_ screenDisplay : ScreenDisplay){
2855+
self.screenDisplay = screenDisplay
2856+
}
2857+
2858+
func execute() {
2859+
screenDisplay.isBatsmanOut()
2860+
}
2861+
}
2862+
2863+
class BatsmanNotOutCommand : Command{
2864+
var screenDisplay : ScreenDisplay
2865+
2866+
init(_ screenDisplay : ScreenDisplay){
2867+
self.screenDisplay = screenDisplay
2868+
}
2869+
2870+
func execute() {
2871+
screenDisplay.isBatsmanNotOut()
2872+
}
2873+
}
2874+
2875+
```
2876+
2877+
We then write two classes BatsmanOutCommand and BatsmanNotOutCommand conforming to Command protocol. Both these classes take a parameter of type ScreenDisplay during their initialisation. Then we write the definition of execute method by calling isBatsmanOut/ isBatsmanNotOut on ScreenDisplay object.
2878+
2879+
```
2880+
class DisplaySwitch {
2881+
var command : Command
2882+
2883+
init(_ command : Command) {
2884+
self.command = command
2885+
}
2886+
2887+
func pressSwitch(){
2888+
command.execute()
2889+
}
2890+
}
2891+
```
2892+
2893+
Finally, we write a class called DisplaySwitch which takes an object of type Command for its initialisation. We define a method called pressSwitch which implements the execute method on Command object.
2894+
Let us write our main method and see our code in action.
2895+
2896+
```
2897+
func main(){
2898+
let screenDisplay = ScreenDisplay()
2899+
2900+
let outCommand = BatsmanOutCommand(screenDisplay)
2901+
let notOutCommand = BatsmanNotOutCommand(screenDisplay)
2902+
2903+
let displaySwitchForOut = DisplaySwitch(outCommand)
2904+
displaySwitchForOut.pressSwitch()
2905+
2906+
let displaySwitchForNotOut = DisplaySwitch(notOutCommand)
2907+
displaySwitchForNotOut.pressSwitch()
2908+
2909+
}
2910+
2911+
main()
2912+
```
2913+
2914+
We take an instance of ScreenDisplay and pass it to BatsmanOutCommand and BatsmanNotOutCommand for their initialisations.
2915+
2916+
Then based on the decision made by the TV umpire, we initialise DisplaySwitch using outCommand / notOutCommand as the parameters.
2917+
2918+
Output in the Xcode console:
2919+
2920+
Batsman is OUT
2921+
Batsman is NOTOUT
2922+
2923+
Summary:
2924+
2925+
When you want to encapsulate the logical details of an operation in a separate entity and define specific instructions for applying the command, Command design pattern serves you the best. It also helps in creating composite commands.
2926+
2927+
**20) Behavioral - Iterator Design Pattern:**
2928+
2929+
Definition:
2930+
2931+
Iteration in coding is a core functionality of various data structures. An iterator facilitates the the traversal of a data structure. Iterator is a behavioral design pattern that is used to sequentially access the elements of an aggregate object without exposing its underlying implementation.
2932+
2933+
Usage:
2934+
2935+
Assume we are making a list of top cricketers in current lot which includes their name and team name. We will now see how to use an Iterator to traverse through the list and print the profile of each cricketer.
2936+
2937+
Let us write some code now:
2938+
2939+
```
2940+
import Foundation
2941+
struct Cricketer{
2942+
let name : String
2943+
let team : String
2944+
}
2945+
```
2946+
2947+
We define a struct named Cricketer which stores name and team as String properties.
2948+
2949+
```
2950+
struct Cricketers{
2951+
let cricketers : [Cricketer]
2952+
}
2953+
```
2954+
2955+
We define another struct named Cricketers which stores cricketers Array of custom type Cricketer.
2956+
2957+
```
2958+
struct CricketersIterator : IteratorProtocol{
2959+
2960+
private var current = 0
2961+
private let cricketers : [Cricketer]
2962+
2963+
init(_ cricketers : [Cricketer]) {
2964+
self.cricketers = cricketers
2965+
}
2966+
2967+
mutating func next() -> Cricketer? {
2968+
defer {
2969+
current += 1
2970+
}
2971+
if cricketers.count > current{
2972+
return cricketers[current]
2973+
} else{
2974+
return nil
2975+
}
2976+
}
2977+
2978+
}
2979+
2980+
extension Cricketers : Sequence{
2981+
func makeIterator() -> CricketersIterator {
2982+
return CricketersIterator(cricketers)
2983+
}
2984+
}
2985+
2986+
```
2987+
2988+
This is where the magic happens. We define a struct named CricketersIterator conforming to IteratorProtocol. Then we write an extension for Cricketers which conforms to Sequence protocol.
2989+
2990+
Apple says ,
2991+
2992+
The IteratorProtocol protocol is tightly linked with the Sequence protocol. Sequences provide access to their elements by creating an iterator, which keeps track of its iteration process and returns one element at a time as it advances through the sequence.
2993+
Whenever you use a for-in loop with an array, set, or any other collection or sequence, you’re using that type’s iterator. Swift uses a sequence’s or collection’s iterator internally to enable the for-in loop language construct.
2994+
Using a sequence’s iterator directly gives you access to the same elements in the same order as iterating over that sequence using a for-in loop.
2995+
2996+
Back to our code, we defined two private properties current of type Int (with default value of 0) and an array cricketers of type Cricketer.
2997+
2998+
We define a method next which returns an object of type Cricketer (notice the optional - we may not have any element left in the array after we reach the last element).
2999+
3000+
Let us now write our main method:
3001+
3002+
```
3003+
func main(){
3004+
let cricketers = Cricketers(cricketers: [Cricketer(name: "Kohli", team: "India"), Cricketer(name: "Steve", team: "Australia"), Cricketer(name: "Kane", team: "Kiwis"), Cricketer(name: "Root", team: "England")])
3005+
for crick in cricketers{
3006+
print(crick)
3007+
}
3008+
}
3009+
3010+
main()
3011+
```
3012+
3013+
Output in the Xcode console:
3014+
3015+
Cricketer(name: "Kohli", team: "India")
3016+
Cricketer(name: "Steve", team: "Australia")
3017+
Cricketer(name: "Kane", team: "Kiwis")
3018+
Cricketer(name: "Root", team: "England")
3019+
3020+
Adding the code snippet for another self explanatory example here which would enhance your understanding:
3021+
3022+
```
3023+
import Foundation
3024+
3025+
class Cricketer : Sequence
3026+
{
3027+
var totalRunsScored = [Int](repeating: 0, count: 3)
3028+
3029+
private let _testRuns = 0
3030+
private let _ODIRuns = 1
3031+
private let _t20Runs = 2
3032+
3033+
var testRuns: Int
3034+
{
3035+
get { return totalRunsScored[_testRuns] }
3036+
set(value) { totalRunsScored[_testRuns] = value }
3037+
}
3038+
3039+
var ODIRuns: Int
3040+
{
3041+
get { return totalRunsScored[_ODIRuns] }
3042+
set(value) { totalRunsScored[_ODIRuns] = value }
3043+
}
3044+
3045+
var t20Runs: Int
3046+
{
3047+
get { return totalRunsScored[_t20Runs] }
3048+
set(value) { totalRunsScored[_t20Runs] = value }
3049+
}
3050+
3051+
var totalRuns: Int
3052+
{
3053+
return totalRunsScored.reduce(0, +)
3054+
}
3055+
3056+
subscript(index: Int) -> Int
3057+
{
3058+
get { return totalRunsScored[index] }
3059+
set(value) { totalRunsScored[index] = value }
3060+
}
3061+
3062+
func makeIterator() -> IndexingIterator<Array<Int>>
3063+
{
3064+
return IndexingIterator(_elements: totalRunsScored)
3065+
}
3066+
}
3067+
3068+
func main()
3069+
{
3070+
let cricketer = Cricketer()
3071+
cricketer.testRuns = 1200
3072+
cricketer.ODIRuns = 1800
3073+
cricketer.t20Runs = 600
3074+
3075+
print("Total Runs Scored = \(cricketer.totalRuns)")
3076+
3077+
for s in cricketer
3078+
{
3079+
print(s)
3080+
}
3081+
}
3082+
3083+
main()
3084+
```
3085+
Output in the Xcode console:
3086+
3087+
Total Runs Scored = 3600
3088+
1200
3089+
1800
3090+
600
3091+
3092+
Summary:
3093+
3094+
When you are in a situation where you want to hide the complexity of a data structure from clients and have a single interface for traversing the data structures, iterator design pattern serves you the best.
3095+

0 commit comments

Comments
 (0)