This commit is contained in:
thomasabishop 2022-06-23 15:26:15 +01:00
parent 0733d76e29
commit e226deae7a
8 changed files with 180 additions and 6 deletions

View file

@ -3,19 +3,19 @@ tags:
- Algorithms_Data_Structures
---
# Arrays
>
> Arrays are used both on their own and to implement many other data structures that place additional restrictions on how the data is manipulated.
> Arrays are used both on their own and to implement many other data structures that place additional restrictions on how the data is manipulated.
## Algorithmic complexity, strict arrays compared with JavaScript
## Algorithmic complexity
In terms of data retrieval arrays have a good runtime since retrieving an element or storing an element takes constant time. Also an entire array takes up O(n) space.
This only applies in the case of strict arrays that exist in strictly typed and more advanced languages such as Java and C++. In JavaScript an array is really closer to a list in other languages. That is to say, it's size (and of course the types it holds) does not need to be known in advance or specified at all. In stricter languages, you would cast the type for the array and specify its length, for example:
````cpp
```cpp
int anArray[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
````
```
Whilst storage and retrieval take place in constant time, deleting and inserting elements through methods like `pop` and `shift` are more time consuming, since the index of every item has to be updated in response.

View file

@ -0,0 +1,81 @@
---
tags:
- Data_Structures
- patterns
- oop
---
# The observer pattern
The Observer design pattern is also known as the 'publish/subscribe' pattern.
> The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
The observer pattern instantiates a **one-to-many** relationship between the subject and its observers: when one object updates, it notifies many other objects that it has been updated.
This is another design pattern that is useful when implementing a global state. When the subject updates its subjects must follow suit and adapt to its changes. Here the subject is the instrument for maintaining the global state.
## Subject class
This class maintains a list of observers that will be notified when it is updated. It should have the following attributes:
- array of existing observers
- an `addObserver` method which pushes an observer onto the observers array
- a `removeObserver` method that does the opposite
- a `notify` method that broadcasts to the observers that a change has happened
## Observer class
Observers must implement an `update` method that will be called by the subject's `notify` method.
## Example
```js
class Subject {
observers = [];
getCurrentTime() {
var d = new Date();
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
}
addObserver(...observer) {
for (const o of observer) {
this.observers.push(o);
}
}
removeObserver(observer) {
const match = this.observers.findIndex((element) => element === observer);
this.observers.splice(match, 1);
}
notify() {
for (const o of this.observers) {
o.update(`I was updated at ${this.getCurrentTime()}`);
}
}
}
class ObserverA {
state = 'I am observer A';
update(newState) {
this.state = newState;
}
}
class ObserverB {
state = 'I am observer B';
update(newState) {
this.state = newState;
}
}
let subjectInstance = new Subject();
let obsAInstance = new ObserverA();
let obsBInstance = new ObserverB();
subjectInstance.addObserver(obsAInstance, obsBInstance);
subjectInstance.notify();
console.log(obsBInstance.state);
```

View file

@ -0,0 +1,94 @@
---
tags:
- Data_Structures
- patterns
- oop
---
# Singleton pattern
As the name suggests, the Singleton pattern is best used in scenarios where you only want to use a single, unique instance of a class. This is for functionality that should only be executed once in the lifecycle of an application. The canonical case would be some kind of bootstrapping process required at initialisation, or initial configuration for an app.
## Use-cases
- Establishing connection to backend database
- API connection (managing tokens so that you are not sending multiple unnecessary calls)
- Configuration settings for an app
- Global state stores in Redux and the React Context API
> With this pattern only one instance of the class can exist. If no instance of the singleton class exists then a new instance is created and returned, but if an instance already exists, then the reference to the existing instance is returned. A singleton should be immutable by the consuming code, and there should be no danger of instantiating more than one of them.
## Implementation
This pattern can be implemented either with a object or a class.
In the example below a global store for a modern JS application is created using an object.
### Using an object
We ensure singularity by:
- using `const` for the object so that it cannot be reassigned
- using `Object.freeze` so that the fields cannot be overwritten, deleted, or additional fields added
```js
const _data = [];
// Methods to add and retrieve data from the store
const UserStore = {
add: (item) => _data.push(item),
get: (id) => _data.find((d) => d.id === id),
};
Object.freeze(UserStore);
export default UserStore;
```
### Using a class
The same process can be created using classes:
```js
class UserStore {
constructor() {
this._data = [];
}
add(item) {
this._data.push(item);
}
get(id) {
return this._data.find((d) => d.id === id);
}
}
const instance = new UserStore();
Object.freeze(instance);
export default instance;
```
Bear in mind that this is really just an ES6 module with `freeze` applied. The only real difference between a singleton and a module is that there should only be one instance of it.
With classes, there is a further step that can be taken to prevent more than once instance of the class being created. This is necessary if you want to be really strict because it is of course possible for a well motivated person to get around the safeguards we established above. We do this by having the class itself check whether there is already an instance of itself. If so, it just returns the already existing instance. We do this by using the self-reference inherent in `this` :
```jsx
class UserStore {
constructor() {
if (!UserStore.instance) {
this._data = [];
UserStore.instance = this;
}
return UserStore.instance;
}
//rest is the same code as preceding example
}
const instance = new UserStore();
Object.freeze(instance);
export default instance;
```

@ -1 +0,0 @@
Subproject commit b56a834d4258d0ce3eeb7bf750209ec35ea69e39