1
00:00:01,000 --> 00:00:02,950
All right, now that we've got the order

2
00:00:02,950 --> 00:00:05,780
objects set up, we can define an abstract

3
00:00:05,780 --> 00:00:08,180
prototype class that all of our cloneable

4
00:00:08,180 --> 00:00:10,310
objects are going to have to inherit from.

5
00:00:10,310 --> 00:00:11,510
I'm going to go up to the top of our

6
00:00:11,510 --> 00:00:15,240
namespace. I'm going to add in a public

7
00:00:15,240 --> 00:00:18,570
abstract class and we'll call it

8
00:00:18,570 --> 00:00:20,930
Prototype. This class is going to

9
00:00:20,930 --> 00:00:23,110
eventually have three methods. A shallow

10
00:00:23,110 --> 00:00:26,500
copy, a deep copy and debug. We've already

11
00:00:26,500 --> 00:00:28,440
implemented the debug in our food order

12
00:00:28,440 --> 00:00:30,510
class, but I like keeping it in the

13
00:00:30,510 --> 00:00:33,050
abstract class so that all prototypeable

14
00:00:33,050 --> 00:00:35,610
objects have to include it. For now, we'll

15
00:00:35,610 --> 00:00:38,020
leave out the deep copy until later in the

16
00:00:38,020 --> 00:00:41,750
clip, Let's add are shallow copy here,

17
00:00:41,750 --> 00:00:44,610
we'll say public abstract. We want this to

18
00:00:44,610 --> 00:00:48,210
return a Prototype object, and it won't

19
00:00:48,210 --> 00:00:52,350
take any arguments. We'll also declare our

20
00:00:52,350 --> 00:00:55,880
public abstract void Debug, and we'll have

21
00:00:55,880 --> 00:01:00,040
our FoodOrder inherit from Prototype. This

22
00:01:00,040 --> 00:01:01,760
makes everything nice and dramatically

23
00:01:01,760 --> 00:01:04,310
sensible. And anyone else on your team is

24
00:01:04,310 --> 00:01:06,670
going to thank you for that. Visual Studio

25
00:01:06,670 --> 00:01:08,620
is yelling at us because FoodOrder does

26
00:01:08,620 --> 00:01:10,760
not actually implement our prototype

27
00:01:10,760 --> 00:01:13,410
methods yet. So let's fix that. Let's add

28
00:01:13,410 --> 00:01:16,930
the override key word to Debug, and

29
00:01:16,930 --> 00:01:19,340
underneath the class constructor we'll add

30
00:01:19,340 --> 00:01:26,610
in our ShallowCopy. We're still going to

31
00:01:26,610 --> 00:01:28,250
get an error because we haven't actually

32
00:01:28,250 --> 00:01:30,715
returned a prototype object. So I'm going

33
00:01:30,715 --> 00:01:32,730
to do that here and then we'll explain

34
00:01:32,730 --> 00:01:35,380
what's going on. I'm going to explicitly

35
00:01:35,380 --> 00:01:37,380
cast whatever we're returning as a

36
00:01:37,380 --> 00:01:39,270
prototype object. And then we're going to

37
00:01:39,270 --> 00:01:40,790
use a new method that you might not have

38
00:01:40,790 --> 00:01:43,690
seen before called MemberwiseClone. Now

39
00:01:43,690 --> 00:01:45,980
what MemberwiseClone does is returns a

40
00:01:45,980 --> 00:01:48,420
shallow copy of the current object. A

41
00:01:48,420 --> 00:01:50,940
shallow copy means that all non‑static

42
00:01:50,940 --> 00:01:53,620
value types in the object are copied over

43
00:01:53,620 --> 00:01:56,160
to the clone. But reference types only

44
00:01:56,160 --> 00:01:58,560
have their addresses copied. That means

45
00:01:58,560 --> 00:02:00,750
that any change to the original object

46
00:02:00,750 --> 00:02:03,050
will also affect the clone, which could be

47
00:02:03,050 --> 00:02:05,180
really troublesome in most cases and is

48
00:02:05,180 --> 00:02:07,600
not the behavior you typically want.

49
00:02:07,600 --> 00:02:09,570
Before we illustrate the drawbacks of

50
00:02:09,570 --> 00:02:11,890
shallow copying, though, let's actually

51
00:02:11,890 --> 00:02:13,530
use the method to make sure that

52
00:02:13,530 --> 00:02:16,150
everything is working properly. Let's go

53
00:02:16,150 --> 00:02:18,640
into our program and underneath where we

54
00:02:18,640 --> 00:02:21,670
did our original order, going to add in a

55
00:02:21,670 --> 00:02:24,440
new Console.WriteLine to remind myself

56
00:02:24,440 --> 00:02:28,480
that this is going to be the Cloned order.

57
00:02:28,480 --> 00:02:31,520
And we'll just create a new FoodOrder,

58
00:02:31,520 --> 00:02:34,850
call it clonedOrder. Make sure to

59
00:02:34,850 --> 00:02:36,980
explicitly cast whatever we're getting

60
00:02:36,980 --> 00:02:40,010
back from our shallow copy and we'll just

61
00:02:40,010 --> 00:02:45,740
say savedOrder.shallowCopy. Now, let's

62
00:02:45,740 --> 00:02:51,440
debug this out, save, and run. Now we can

63
00:02:51,440 --> 00:02:53,620
see here that both of our food orders are

64
00:02:53,620 --> 00:02:55,800
exactly the same, as we don't have any

65
00:02:55,800 --> 00:02:58,130
embedded reference types. A note here,

66
00:02:58,130 --> 00:03:00,320
strings are technically referenced types

67
00:03:00,320 --> 00:03:02,610
in the C# language. But in this instance,

68
00:03:02,610 --> 00:03:06,200
they transfer over when shallow copied. To

69
00:03:06,200 --> 00:03:09,090
see the drawbacks of shallow copying in

70
00:03:09,090 --> 00:03:10,850
action, let's go back to our food order,

71
00:03:10,850 --> 00:03:13,700
and we're going to create a class that's

72
00:03:13,700 --> 00:03:16,080
going to hold an order ID number. And then

73
00:03:16,080 --> 00:03:19,170
we're going to add a type of that class to

74
00:03:19,170 --> 00:03:23,250
our food order itself. So underneath

75
00:03:23,250 --> 00:03:25,060
Prototype, I'm just going to say public

76
00:03:25,060 --> 00:03:29,440
class, I'm going to call this OrderInfo.

77
00:03:29,440 --> 00:03:31,915
It's going to have one field. It's a

78
00:03:31,915 --> 00:03:35,360
integer, we'll call it id, and we'll give

79
00:03:35,360 --> 00:03:43,870
it a constructor to set that ID. Let's go

80
00:03:43,870 --> 00:03:45,370
down to our food order underneath

81
00:03:45,370 --> 00:03:48,380
orderContents and we'll say public

82
00:03:48,380 --> 00:03:50,580
OrderInfo, and I'm going to call this

83
00:03:50,580 --> 00:03:53,350
info, and we need to change our

84
00:03:53,350 --> 00:03:57,450
constructor. So we'll do that real quick,

85
00:03:57,450 --> 00:04:03,560
and save it off. Perfect. Now let's go

86
00:04:03,560 --> 00:04:06,420
down to the debug and we'll add one more

87
00:04:06,420 --> 00:04:08,600
Console.WriteLine so that our new property

88
00:04:08,600 --> 00:04:13,100
is printed out. We'll say ID and we'll use

89
00:04:13,100 --> 00:04:17,680
this.info.id. Wonderful. Now, while we're

90
00:04:17,680 --> 00:04:20,120
here, let's test this out by changing the

91
00:04:20,120 --> 00:04:22,690
name and order number of our originally

92
00:04:22,690 --> 00:04:26,250
saved order inside our main program.

93
00:04:26,250 --> 00:04:27,710
Actually, before that, we do need to

94
00:04:27,710 --> 00:04:29,930
update our constructor for our original

95
00:04:29,930 --> 00:04:33,270
order. So we'll do that real quick, after

96
00:04:33,270 --> 00:04:36,550
our contents, we'll add a new OrderInfo

97
00:04:36,550 --> 00:04:42,570
object with the ID 2345. Why not?

98
00:04:42,570 --> 00:04:44,530
Underneath our cloned order let's add

99
00:04:44,530 --> 00:04:48,850
another WriteLine to remind ourselves that

100
00:04:48,850 --> 00:04:51,280
what's printed out after this is the Order

101
00:04:51,280 --> 00:04:53,040
changes. And we'll say

102
00:04:53,040 --> 00:04:56,720
savedOrder.customerName and we'll change

103
00:04:56,720 --> 00:05:02,670
this to Jeff, savedOrder.info.id. We'll

104
00:05:02,670 --> 00:05:05,810
change it to all fives and we'll print

105
00:05:05,810 --> 00:05:11,590
both of these out again. Make sure to save

106
00:05:11,590 --> 00:05:13,160
and let's give this a run and see what

107
00:05:13,160 --> 00:05:16,450
we've got in our console. All right, so,

108
00:05:16,450 --> 00:05:18,300
looking at the output, it's going to show

109
00:05:18,300 --> 00:05:20,540
us that the name change in our original

110
00:05:20,540 --> 00:05:22,470
order didn't affect the clone, which is

111
00:05:22,470 --> 00:05:25,160
great. However, the change to the original

112
00:05:25,160 --> 00:05:28,200
order ID affected the clone, and now it's

113
00:05:28,200 --> 00:05:31,280
5555, as with the original. Now to get

114
00:05:31,280 --> 00:05:32,780
around this, we're going to implement

115
00:05:32,780 --> 00:05:34,800
what's called deep copying, and that's

116
00:05:34,800 --> 00:05:37,150
going to account for the reference types

117
00:05:37,150 --> 00:05:39,460
being separate in an original and cloned

118
00:05:39,460 --> 00:05:41,890
object. And this could be done in a few

119
00:05:41,890 --> 00:05:44,470
ways. But the easiest is to simply add a

120
00:05:44,470 --> 00:05:47,040
deep copy method to our prototype class

121
00:05:47,040 --> 00:05:49,350
and manually configure our reference type

122
00:05:49,350 --> 00:05:51,490
after creating a shallow clone. Let's go

123
00:05:51,490 --> 00:05:54,350
back into our food order. We'll go up to

124
00:05:54,350 --> 00:05:57,020
our prototype class. We're going to add in

125
00:05:57,020 --> 00:06:00,460
a new method. This is going to also return

126
00:06:00,460 --> 00:06:03,060
prototype object, and it's going to be

127
00:06:03,060 --> 00:06:07,380
called DeepCopy. We're going to go down to

128
00:06:07,380 --> 00:06:10,650
our food order, below ShallowCopy, let's

129
00:06:10,650 --> 00:06:15,630
implement this. Say public override

130
00:06:15,630 --> 00:06:20,720
Prototype DeepCopy. And let's actually

131
00:06:20,720 --> 00:06:24,045
just make the shallow clone first. So,

132
00:06:24,045 --> 00:06:29,430
we'll say FoodOrder clonedOrder we'll

133
00:06:29,430 --> 00:06:32,190
explicitly cast it, and we'll use

134
00:06:32,190 --> 00:06:35,060
MemberwiseClone once again. After

135
00:06:35,060 --> 00:06:36,780
wondering why I just didn't call are

136
00:06:36,780 --> 00:06:39,170
shallow copy method, it's because in most

137
00:06:39,170 --> 00:06:42,520
cases you won't have both of these in your

138
00:06:42,520 --> 00:06:44,310
program. You'll want to choose which one

139
00:06:44,310 --> 00:06:45,930
suits your needs. So I'm going to keep

140
00:06:45,930 --> 00:06:48,510
them completely separate. Once we've got a

141
00:06:48,510 --> 00:06:50,580
new shallow copy, we can account for the

142
00:06:50,580 --> 00:06:54,530
reference. We can just set our info to a

143
00:06:54,530 --> 00:06:57,150
brand new instance of OrderInfo. And we

144
00:06:57,150 --> 00:06:59,350
can initialize it to get the actual copy

145
00:06:59,350 --> 00:07:01,450
of the object we're working with by saying

146
00:07:01,450 --> 00:07:08,800
this.info.id and return the cloned order.

147
00:07:08,800 --> 00:07:11,120
If we go back to our program, we're going

148
00:07:11,120 --> 00:07:13,770
to change our shallow copy method call to

149
00:07:13,770 --> 00:07:18,510
DeepCopy, save it off, and run. Now we can

150
00:07:18,510 --> 00:07:20,960
see in our Order changes section that our

151
00:07:20,960 --> 00:07:24,080
original object has been changed with the

152
00:07:24,080 --> 00:07:26,310
name and ID, but our cloned object is

153
00:07:26,310 --> 00:07:29,130
exactly the same as the first instance

154
00:07:29,130 --> 00:07:31,570
before the changes took effect. With that

155
00:07:31,570 --> 00:07:33,340
done, we've successfully implemented a

156
00:07:33,340 --> 00:07:35,790
basic prototype pattern. All that's left

157
00:07:35,790 --> 00:07:38,470
is to touch on a popular variant using a

158
00:07:38,470 --> 00:07:43,000
prototype manager class, which we'll do in the next clip

