You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+289Lines changed: 289 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2804,3 +2804,292 @@ Summary:
2804
2804
2805
2805
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.
2806
2806
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).
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.
0 commit comments