2015-08-13 23:54:40 +02:00
|
|
|
---
|
|
|
|
layout: pattern
|
|
|
|
title: Private Class Data
|
|
|
|
folder: private-class-data
|
2015-08-15 18:03:05 +02:00
|
|
|
permalink: /patterns/private-class-data/
|
2019-12-13 21:09:28 +02:00
|
|
|
categories: Idiom
|
2021-05-19 10:49:05 -06:00
|
|
|
language: en
|
2015-12-28 15:52:44 +02:00
|
|
|
tags:
|
2019-12-13 21:09:28 +02:00
|
|
|
- Data access
|
2015-08-13 23:54:40 +02:00
|
|
|
---
|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
## 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.
|
2015-08-13 23:54:40 +02:00
|
|
|
|
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
|
2021-03-13 13:19:21 +01:00
|
|
|
@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;
|
|
|
|
}
|
|
|
|
}
|
2021-03-13 13:19:21 +01:00
|
|
|
@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
|
|
|
|
```
|
|
|
|
|
2019-12-07 20:01:13 +02:00
|
|
|
## Class diagram
|
2020-09-01 19:55:22 +03:00
|
|
|
|
2015-08-13 23:54:40 +02:00
|
|
|

|
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
## Applicability
|
2020-09-01 19:55:22 +03:00
|
|
|
|
2016-01-03 21:14:30 +01:00
|
|
|
Use the Private Class Data pattern when
|
2015-08-13 23:54:40 +02:00
|
|
|
|
2020-09-01 19:55:22 +03:00
|
|
|
* You want to prevent write access to class data members.
|