137 lines
3.8 KiB
Markdown
Raw Permalink Normal View History

---
layout: pattern
title: Private Class Data
folder: private-class-data
permalink: /patterns/private-class-data/
categories: Idiom
language: en
2015-12-28 15:52:44 +02:00
tags:
- Data access
---
## Intent
2020-09-01 19:55:22 +03:00
2020-08-09 21:49:00 +03:00
Private Class Data design pattern seeks to reduce exposure of attributes by limiting their
visibility. It reduces the number of class attributes by encapsulating them in single Data object.
2020-08-09 03:09:53 +08:00
## Explanation
Real world example
2020-08-09 21:49:00 +03:00
> Imagine you are cooking a stew for your family for dinner. You want to prevent your family members
> from consuming the stew by tasting it while you are cooking, otherwise there will be no more stew
> for dinner later.
2020-08-09 03:10:43 +08:00
2020-08-09 03:09:53 +08:00
In plain words
2020-08-09 21:49:00 +03:00
> Private class data pattern prevents manipulation of data that is meant to be immutable by
> separating the data from the methods that use it into a class that maintains the data state.
2020-08-09 03:10:43 +08:00
2020-08-09 03:09:53 +08:00
Wikipedia says
2020-08-09 21:49:00 +03:00
> Private class data is a design pattern in computer programming used to encapsulate class
> attributes and their manipulation.
2020-08-09 03:10:43 +08:00
2020-08-09 03:09:53 +08:00
**Programmatic Example**
2020-08-09 21:49:00 +03:00
Taking our stew example from above. First we have a `Stew` class where its data is not protected by
private class data, making the stew's ingredient mutable to class methods.
2020-08-09 03:09:53 +08:00
2020-08-09 21:54:54 +03:00
```java
@Slf4j
2020-08-09 03:09:53 +08:00
public class Stew {
private int numPotatoes;
private int numCarrots;
private int numMeat;
private int numPeppers;
public Stew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {
this.numPotatoes = numPotatoes;
this.numCarrots = numCarrots;
this.numMeat = numMeat;
this.numPeppers = numPeppers;
}
public void mix() {
LOGGER.info("Mixing the stew we find: {} potatoes, {} carrots, {} meat and {} peppers",
numPotatoes, numCarrots, numMeat, numPeppers);
}
public void taste() {
LOGGER.info("Tasting the stew");
if (numPotatoes > 0) {
numPotatoes--;
}
if (numCarrots > 0) {
numCarrots--;
}
if (numMeat > 0) {
numMeat--;
}
if (numPeppers > 0) {
numPeppers--;
}
}
}
```
2020-08-09 21:49:00 +03:00
Now, we have `ImmutableStew` class, where its data is protected by `StewData` class. Now, the
methods in are unable to manipulate the data of the `ImmutableStew` class.
2020-08-09 21:54:54 +03:00
```java
2020-08-09 03:09:53 +08:00
public class StewData {
private final int numPotatoes;
private final int numCarrots;
private final int numMeat;
private final int numPeppers;
public StewData(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {
this.numPotatoes = numPotatoes;
this.numCarrots = numCarrots;
this.numMeat = numMeat;
this.numPeppers = numPeppers;
}
public int getNumPotatoes() {
return numPotatoes;
}
public int getNumCarrots() {
return numCarrots;
}
public int getNumMeat() {
return numMeat;
}
public int getNumPeppers() {
return numPeppers;
}
}
@Slf4j
2020-08-09 03:09:53 +08:00
public class ImmutableStew {
private final StewData data;
public ImmutableStew(int numPotatoes, int numCarrots, int numMeat, int numPeppers) {
data = new StewData(numPotatoes, numCarrots, numMeat, numPeppers);
}
public void mix() {
LOGGER
.info("Mixing the immutable stew we find: {} potatoes, {} carrots, {} meat and {} peppers",
data.getNumPotatoes(), data.getNumCarrots(), data.getNumMeat(), data.getNumPeppers());
}
}
```
2020-08-09 21:49:00 +03:00
Let's try creating an instance of each class and call their methods:
2020-08-09 21:54:54 +03:00
```java
2020-08-09 03:09:53 +08:00
var stew = new Stew(1, 2, 3, 4);
stew.mix(); // Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers
stew.taste(); // Tasting the stew
stew.mix(); // Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers
var immutableStew = new ImmutableStew(2, 4, 3, 6);
immutableStew.mix(); // Mixing the immutable stew we find: 2 potatoes, 4 carrots, 3 meat and 6 peppers
```
## Class diagram
2020-09-01 19:55:22 +03:00
![alt text](./etc/private-class-data.png "Private Class Data")
## Applicability
2020-09-01 19:55:22 +03:00
Use the Private Class Data pattern when
2020-09-01 19:55:22 +03:00
* You want to prevent write access to class data members.