Skip to content

Commit bd88638

Browse files
Update README.md
1 parent df39bcd commit bd88638

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

README.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,3 +1297,192 @@ If you are trying to use the same code for building different products to isolat
12971297

12981298
Also be careful that when your product does not require multiple parameters for initialisation or construction, it’s advised to stay away from Builder pattern.
12991299

1300+
**8) Creational - Prototype Design Pattern:**
1301+
1302+
Definition:
1303+
1304+
Prototype is a creational design pattern used in situations which lets us produce new objects, that are almost similar state or differs little. A prototype is basically a template of any object before the actual object is constructed. The Prototype pattern delegates cloning process to objects themselves.
1305+
1306+
Usage:
1307+
1308+
Let us consider a simple use case where we want to create the profile of two cricketers which includes their name, and a custom profile which includes runs scored and wickets taken.
1309+
1310+
```
1311+
import UIKit
1312+
1313+
class Profile : CustomStringConvertible{
1314+
var runsScored : Int
1315+
var wicketsTaken : Int
1316+
1317+
init(_ runsScored : Int, _ wicketsTaken : Int) {
1318+
self.runsScored = runsScored
1319+
self.wicketsTaken = wicketsTaken
1320+
}
1321+
1322+
var description: String{
1323+
return "\(runsScored) Runs Scored & \(wicketsTaken) Wickets Taken"
1324+
}
1325+
}
1326+
1327+
```
1328+
1329+
First, we create a Profile class which conforms to CustomStringConvertible. It has two properties runsScored and wicketsTaken of type int. It takes the same parameters during its initialisation.
1330+
1331+
Then we define a Cricketer class conforms to CustomStringConvertible. It has two properties, name of type String and profile of custom type Profile which we just created.
1332+
1333+
```
1334+
class Cricketer : CustomStringConvertible {
1335+
var name : String
1336+
var profile : Profile
1337+
1338+
init(_ name :String , _ profile : Profile) {
1339+
self.name = name
1340+
self.profile = profile
1341+
}
1342+
var description: String{
1343+
return "\(name) : Profile : \(profile)"
1344+
}
1345+
1346+
}
1347+
```
1348+
1349+
Let us now write a function called main to see the things in action.
1350+
1351+
```
1352+
func main (){
1353+
let profile = Profile(1200, 123)
1354+
let bhuvi = Cricketer("Bhuvi", profile)
1355+
print(bhuvi.description)
1356+
}
1357+
1358+
main()
1359+
```
1360+
1361+
It prints
1362+
1363+
Bhuvi : Profile : 1200 Runs Scored & 123 Wickets Taken in the Xcode console.
1364+
1365+
Now we need to talk about copying the objects.
1366+
1367+
Just before print statement in the main function, add the following lines .
1368+
1369+
```
1370+
var ishant = bhuvi
1371+
ishant.name = "Ishant"
1372+
print(ishant.description)
1373+
```
1374+
It prints
1375+
Ishant : Profile : 1200 Runs Scored & 123 Wickets Taken
1376+
Ishant : Profile : 1200 Runs Scored & 123 Wickets Taken
1377+
1378+
in the Xcode console.
1379+
1380+
This is because we are only copying the references.
1381+
1382+
Now add this line just before printing ishant’s description.
1383+
1384+
```ishant.profile.runsScored = 600```
1385+
1386+
It prints
1387+
Ishant : Profile : 600 Runs Scored & 123 Wickets Taken
1388+
Ishant : Profile : 600 Runs Scored & 123 Wickets Taken
1389+
1390+
in the Xcode console.
1391+
1392+
Now, we need to make sure bhuvi and ishant actually refer to different objects.
1393+
1394+
Here, we use the concept of Deep Copy. When we deep copy objects, the system will copy references and each copied reference will be pointing to its own copied memory object. Let us now see how to implement Deep Copy interface for our use case.
1395+
1396+
```
1397+
protocol DeepCopy{
1398+
func createDeepCopy () -> Self
1399+
}
1400+
1401+
```
1402+
1403+
First, we create a DeepCopy protocol which defines a function called createDeepCopy returning self.
1404+
1405+
Then make the classes Profile and Cricketer conform to DeepCopy protocol. Classes now look like:
1406+
1407+
```
1408+
class Profile : CustomStringConvertible, DeepCopy{
1409+
var runsScored : Int
1410+
var wicketsTaken : Int
1411+
1412+
init(_ runsScored : Int, _ wicketsTaken : Int) {
1413+
self.runsScored = runsScored
1414+
self.wicketsTaken = wicketsTaken
1415+
}
1416+
1417+
var description: String{
1418+
return "\(runsScored) Runs Scored & \(wicketsTaken) Wickets Taken"
1419+
}
1420+
1421+
func createDeepCopy() -> Self {
1422+
return deepCopyImplementation()
1423+
}
1424+
1425+
private func deepCopyImplementation <T> () -> T{
1426+
return Profile(runsScored, wicketsTaken) as! T
1427+
}
1428+
}
1429+
```
1430+
1431+
We have a private method called deepCopyImplementation which is generic and and able to figure out the type correctly. It has a type parameter ‘T’ which is actually going to be inferred (we don’t provide this type parameter anywhere) and a return type of ‘T’. We return a Profile objects and force cast it to T.
1432+
1433+
Cricketer class now looks like:
1434+
1435+
```
1436+
class Cricketer : CustomStringConvertible ,DeepCopy{
1437+
var name : String
1438+
var profile : Profile
1439+
1440+
init(_ name :String , _ profile : Profile) {
1441+
self.name = name
1442+
self.profile = profile
1443+
}
1444+
1445+
var description: String{
1446+
return "\(name) : Profile : \(profile)"
1447+
}
1448+
1449+
func createDeepCopy() -> Self {
1450+
return deepCopyImplementation()
1451+
}
1452+
1453+
private func deepCopyImplementation <T> () -> T{
1454+
return Cricketer(name, profile) as! T
1455+
}
1456+
1457+
}
1458+
```
1459+
Let us define our main method as below and see the results:
1460+
1461+
```
1462+
func main(){
1463+
let profile = Profile(1200, 123)
1464+
let bhuvi = Cricketer("Bhuvi", profile)
1465+
let ishant = bhuvi.createDeepCopy()
1466+
ishant.name = "Ishant"
1467+
ishant.profile = bhuvi.profile.createDeepCopy()
1468+
ishant.profile.wicketsTaken = 140
1469+
print(bhuvi.description)
1470+
print(ishant.description)
1471+
}
1472+
1473+
main()
1474+
```
1475+
1476+
Output in the Xcode console:
1477+
1478+
Bhuvi : Profile : 1200 Runs Scored & 123 Wickets Taken
1479+
Ishant : Profile : 1200 Runs Scored & 140 Wickets Taken
1480+
1481+
We can see that bhuvi and ishant are two different objects now and this is how deep copy is implemented.
1482+
1483+
Summary:
1484+
1485+
When you are in a situation to clone objects without coupling to their concrete classes, you can opt for Prototype design pattern which also helps in reducing repetitive initialization code.
1486+
1487+
1488+

0 commit comments

Comments
 (0)