I want to show you something a bit more sophisticated which is actually an intersection of the composite
and proxied design patterns.
And it's to do with the ways that fields are actually exposed from objects.
So let me show you what's going on with this particular approach.
Let's suppose that we come back to our example of a creature in a computer game so you have a class
called creature and the creature has certain statistics So for example a creature might have strength
intelligence agility.
Let's actually have those strength intelligence and agility as well so maybe other properties can be
added later on.
So essentially what you do is you go ahead and you expose these properties as a bunch of getters and
setters so here we can go ahead and we can just use whatever Sea-Lion gives us to generate the Gethers
in the Seto's.
Now here is the thing in addition to having all of these values stored separately sometimes you want
to perform aggregate count collations.
Now typically when we have a computer game you might want to for example figure out the average statistic
of a creature or you might want to find out the maximum statistic of a creature.
So if you were to just take this approach like I've implemented it here then the implementation of aggregate
calculations becomes really painful.
For example if I won the sum of all the properties I have to return strength plus agility plus intelligence
intelligence and then from this if I want the average For example let's suppose I won the average here
if I won the average then I would have to take the sum and divided by 3.00 3.0 is of course my kind
of inbuilt knowledge of the fact that I have three properties available to me.
And let's also look at maximum so if I want the maximum ability out of all the abilities so the one
with the highest value I would say I'm going to return the maximum of the maximum of strength.
Gelati and intelligence.
OK so as you can see this approach is ugly and it doesn't really scale in the sense that for example
if I had let's say not three probably but six of these it would be really tedious to type all this stuff
up and fold all these maximum calculations together.
Furthermore imagine if I implement the creature and I want to add another property Lesbos I want to
add something like wisdom or charisma or something else I would have to go into every single aggregate
and I would have to rewrite them because here I would have to say plus plus wisdom here I would have
to divide by 4 here I would have to totally reshuffle the definition of the maximum function to maybe
add additional calls to Max because each one of these takes two arguments.
So this is particularly problematic and there is a fix for this which should explain to you what the
Composite pattern has to do with this and that is the idea of having aggregate storage or composite
storage for the actual fields.
So we certainly have properties effectively that we're exposing but the fields don't need to be stored
as separate fields.
There is no benefit to having them separate because sure we expose them here but that's all kind of
internal implementation details.
Nobody really goes into those fields from the outside because they're private.
So let's see if we can rewrite the creature using an approach called array back properties.
So we're going to have a new creature object which is going to be a bit more sophisticated shall we
say.
OK let's go here.
OK so here is a better class creature.
Now what we're going to do is first of all it will define the set of abilities that a creature actually
has and a good place to do that is in and you know so I'm going to have them called abilities and we'll
just have a list of shorthand names of the abilities that the creature has.
So for example strength or agility or intelligence.
Now I'm going to add another terminating element.
Now you might have seen this already practiced by some C++ developers where you have an income and you
add a terminating element because that value of that terminating element is the number of the abilities
that you actually have.
So here I'm going to put count.
So what this means is at the moment we have value 0 1 2 and 3.
Now if you want to know how many actual abilities we have in the list we have three abilities.
One two and three.
And the value of count is precisely that it's three.
So what we can do now is we can use this count to make an array and store the actual values of those
abilities in an array.
So I make an array that is an ordinary SDD array.
I specify the type is int and notice here is the fun part.
I specify the length of the array as the count from the enim and I call it abilities.
So now what we need to do is to generate the getters and setters for the actual properties.
Unfortunately the word generate isn't applicable here because sea line or any other ID doesn't know
about the array back approach.
So we have to write those ourselves.
For example if I want to expose the strength here is how I would do it I would say it gets strength
and I would return abilities at.
And I would use the enum once again abilities and as TR notes is I'm using a good old fashioned e now
not an M-class which means I get sort of automatic conversion to integer and I can use it as an index
without any kind of problem.
And the same will go for the setter.
So set strength
where you will take abilities once again it index has TR and you would assign the value.
So this is how you would go ahead and implement the getters and setters.
Now I'm not going to bore you with actually typing out the ones for agility and then tell it just let
me actually just drop them in here.
So there we go.
OK so this is how you do the Gethers and the centers.
But the upside of this approach is that you now have all of the abilities stored in a single array which
means if you want to calculate the sum or the average or the maximum or any other kind of aggregate
opera operations you don't have to write ugly code like this.
I mean seriously you don't have to put in magic numbers because this 3.00 here is obviously a magic
number it corresponds to the number of the fields you actually have but it's completely unnecessary
So let's see if we can implement those same members in a much nicer way we'll begin with some.
So let's suppose I wanted to calculate the sum of all the abilities all you have to do is call a cumi.
That's as simple as that you call cumulate you pass it abilities that begin abilities and and Asier
and that's it you've got your sum basically.
So now if you want to calculate the average what you can do is you can get the sum but you don't have
to divide it by a magic number.
You return some divided by and you simply take count because remember count here.
We're using it once again and we can cast it to a double like so.
So there we go.
You have your average implementation and for the maximum if you want the maximum ability for example
that's once again very easy because we already have functions for these aggregate calculations.
You simply return you dereference Max element.
So Max element gives you a pointer to the largest element and you say abilities that begin abilities.
And there we go.
So that's pretty much all that you have to do.
Now we can actually try using these aggregate.
So I just want to show you the fact that this approach actually works so we're going to have a creature
called an orc is going to be powerful but not particularly intelligent so we're going to have orc darts
strength.
Set it to a high value is 16.
For example let's say borke those set agility.
So we're going to set the agility to 11 and orc's set intelligence not very intelligent but it has a
9 and what we can do now is we can get those stats printed.
So I can say that the Orrick has an average
statistic of that's calculated so Ordog average and and a maximum statistic.
All of us calculate the maximum orch don't max that would go.
All right.
So it's as simple as that really and let's see what we get here.
All right you can see what we're getting is we're getting the orch has an average of 12.
And indeed if you add those up you get 36 which divided by three is 12 and the maximum statistic is
16.
So what ever tempted to demonstrate in this example is there is no reason to have a backing field as
backing.
You can have just a single field which has an array of everything and then whenever you have actual
properties like strengthen Jolter intelligence you simply project them onto this array.
And of course the end user the client that's consuming the API doesn't really need to know about this
they don't care about the implementation so long as it works and you have this nice contiguous chunk
of memory here that you can work with and all of those wonderful operations from the standard library
are suddenly available to you.
So calculating sums and averages many hours maximum kind of moving averages if that's what you want
this whole becomes a lot easier with this approach.