restructure

This commit is contained in:
JMARyA 2024-01-17 09:00:45 +01:00
parent ef7661245b
commit 598a10bc28
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
182 changed files with 342 additions and 336 deletions

View file

@ -5,8 +5,8 @@ obj: meta/collection
# Development
## Languages
- [Python](../programming/languages/Python.md)
- [Rust](../programming/languages/Rust.md)
- [Python](programming/languages/Python.md)
- [Rust](programming/languages/Rust.md)
## Tools
- [Git](Git.md)

View file

@ -57,7 +57,7 @@ git log --graph --oneline --decorate
```
### Commits
Git allows commits and tags to be signed using [GnuPG](../tools/GPG.md).
Git allows commits and tags to be signed using [GnuPG](../cryptography/GPG.md).
```shell
git config --global commit.gpgSign true`
```

View file

@ -0,0 +1,629 @@
---
obj: concept
website: https://github.com/features/actions
---
# GitHub Actions
GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.
GitHub Actions goes beyond just DevOps and lets you run workflows when other events happen in your repository. For example, you can run a workflow to automatically add the appropriate labels whenever someone creates a new issue in your repository.
You can configure a GitHub Actions _workflow_ to be triggered when an _event_ occurs in your repository, such as a pull request being opened or an issue being created. Your workflow contains one or more _jobs_ which can run in sequential order or in parallel. Each job will run inside its own virtual machine _runner_, or inside a container, and has one or more _steps_ that either run a script that you define or run an _action_, which is a reusable extension that can simplify your workflow.
Example:
```yml
name: Rust
on:
push:
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
```
## Expressions
You can use expressions to programmatically set [environment variables](../linux/Environment%20Variables.md) in workflow files and access contexts. An expression can be any combination of literal values, references to a context, or functions. You can combine literals, context references, and functions using operators.
Expressions are commonly used with the conditional `if` keyword in a workflow file to determine whether a step should run. When an `if` conditional is `true`, the step will run.
You need to use specific syntax to tell [GitHub](GitHub.md) to evaluate an expression rather than treat it as a string.
`${{ <expression> }}`
Secrets passed to GitHub Actions can be used:
`${{ secrets.MYSECRET }}`
### Functions
#### contains
`contains( search, item )`
Returns `true` if `search` contains `item`. If `search` is an array, this function returns `true` if the `item` is an element in the array. If `search` is a string, this function returns `true` if the `item` is a substring of `search`. This function is not case sensitive. Casts values to a string.
#### startsWith
`startsWith( searchString, searchValue )`
Returns `true` when `searchString` starts with `searchValue`. This function is not case sensitive. Casts values to a string.
#### endsWith
`endsWith( searchString, searchValue )`
Returns `true` if `searchString` ends with `searchValue`. This function is not case sensitive. Casts values to a string.
#### format
`format( string, replaceValue0, replaceValue1, ..., replaceValueN)`
Replaces values in the `string`, with the variable `replaceValueN`. Variables in the `string` are specified using the `{N}` syntax, where `N` is an integer. You must specify at least one `replaceValue` and `string`. There is no maximum for the number of variables (`replaceValueN`) you can use. Escape curly braces using double braces.
#### always
Causes the step to always execute, and returns `true`, even when canceled. The `always` expression is best used at the step level or on tasks that you expect to run even when a job is canceled. For example, you can use `always` to send logs even when a job is canceled.
Example of `always`:
```yaml
if: ${{ always() }}
```
#### failure
Returns `true` when any previous step of a job fails. If you have a chain of dependent jobs, `failure()` returns `true` if any ancestor job fails.
Example of `failure`:
```yaml
steps:
...
- name: The job has failed
if: ${{ failure() }}
```
## Workflows
A workflow is a configurable automated process that will run one or more jobs. Workflows are defined by a [YAML](../files/YAML.md) file checked in to your repository and will run when triggered by an event in your repository, or they can be triggered manually, or at a defined schedule.
Workflows are defined in the `.github/workflows` directory in a repository, and a repository can have multiple workflows, each of which can perform a different set of tasks. For example, you can have one workflow to build and test pull requests, another workflow to deploy your application every time a release is created, and still another workflow that adds a label every time someone opens a new issue.
### Syntax
#### `name`
The name of the workflow. [GitHub](GitHub.md) displays the names of your workflows under your repository's "Actions" tab. If you omit `name`, [GitHub](GitHub.md) displays the workflow file path relative to the root of the repository.
#### `on`
To automatically trigger a workflow, use `on` to define which events can cause the workflow to run.
You can define single or multiple events that can trigger a workflow, or set a time schedule. You can also restrict the execution of a workflow to only occur for specific files, tags, or branch changes. These options are described in the following sections.
**Using a single event:**
For example, a workflow with the following `on` value will run when a push is made to any branch in the workflow's repository:
```yaml
on: push
```
**Using multiple events:**
You can specify a single event or multiple events. For example, a workflow with the following `on` value will run when a push is made to any branch in the repository or when someone forks the repository:
```yaml
on: [push, fork]
```
If you specify multiple events, only one of those events needs to occur to trigger your workflow. If multiple triggering events for your workflow occur at the same time, multiple workflow runs will be triggered.
**Using activity types:**
Some events have activity types that give you more control over when your workflow should run. Use `on.<event_name>.types` to define the type of event activity that will trigger a workflow run.
For example, the `issue_comment` event has the `created`, `edited`, and `deleted` activity types. If your workflow triggers on the `label` event, it will run whenever a label is created, edited, or deleted. If you specify the `created` activity type for the `label` event, your workflow will run when a label is created but not when a label is edited or deleted.
```yaml
on:
label:
types:
- created
```
If you specify multiple activity types, only one of those event activity types needs to occur to trigger your workflow. If multiple triggering event activity types for your workflow occur at the same time, multiple workflow runs will be triggered. For example, the following workflow triggers when an issue is opened or labeled. If an issue with two labels is opened, three workflow runs will start: one for the issue opened event and two for the two issue labeled events.
```yaml
on:
issues:
types:
- opened
- labeled
```
**Using filters:**
Some events have filters that give you more control over when your workflow should run.
For example, the `push` event has a `branches` filter that causes your workflow to run only when a push to a branch that matches the `branches` filter occurs, instead of when any push occurs.
```yaml
on:
push:
branches:
- main
- 'releases/**'
```
#### `on.<event_name>.types`
Use `on.<event_name>.types` to define the type of activity that will trigger a workflow run. Most [GitHub](GitHub.md) events are triggered by more than one type of activity. For example, the `label` is triggered when a label is `created`, `edited`, or `deleted`. The `types` keyword enables you to narrow down activity that causes the workflow to run. When only one activity type triggers a [webhook](../internet/Webhook.md) event, the `types` keyword is unnecessary.
```yaml
on:
label:
types: [created, edited]
```
#### `on.schedule`
You can use `on.schedule` to define a time schedule for your workflows. You can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes.
This example triggers the workflow every day at 5:30 and 17:30 UTC:
```yaml
on:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '30 5,17 * * *'
```
A single workflow can be triggered by multiple `schedule` events. You can access the schedule event that triggered the workflow through the `github.event.schedule` context. This example triggers the workflow to run at 5:30 UTC every Monday-Thursday, but skips the `Not on Monday or Wednesday` step on Monday and Wednesday.
```yaml
on:
schedule:
- cron: '30 5 * * 1,3'
- cron: '30 5 * * 2,4'
jobs:
test_schedule:
runs-on: ubuntu-latest
steps:
- name: Not on Monday or Wednesday
if: github.event.schedule != '30 5 * * 1,3'
run: echo "This step will be skipped on Monday and Wednesday"
- name: Every time
run: echo "This step will always run"
```
#### `on.workflow_dispatch`
When using the `workflow_dispatch` event, you can manually run this workflow from the UI.
#### `env`
A `map` of variables that are available to the steps of all jobs in the workflow. You can also set variables that are only available to the steps of a single job or to a single step. For more information, see `jobs.<job_id>.env` and `jobs.<job_id>.steps[*].env`.
Variables in the `env` map cannot be defined in terms of other variables in the map.
**Example of `env`:**
```yaml
env:
SERVER: production
```
#### `jobs`
A workflow run is made up of one or more `jobs`, which run in parallel by default. To run jobs sequentially, you can define dependencies on other jobs using the `jobs.<job_id>.needs` keyword.
Each job runs in a runner environment specified by `runs-on`.
##### `jobs.<job_id>`
Use `jobs.<job_id>` to give your job a unique identifier. The key `job_id` is a string and its value is a map of the job's configuration data. You must replace `<job_id>` with a string that is unique to the `jobs` object. The `<job_id>` must start with a letter or `_` and contain only alphanumeric characters, `-`, or `_`.
Use `jobs.<job_id>.name` to set a name for the job, which is displayed in the [GitHub](GitHub.md) UI.
**Example: Creating jobs:**
In this example, two jobs have been created, and their `job_id` values are `my_first_job` and `my_second_job`.
```yaml
jobs:
my_first_job:
name: My first job
my_second_job:
name: My second job
```
##### `jobs.<job_id>.container`
Use `jobs.<job_id>.container` to create a container to run any steps in a job that don't already specify a container. If you have steps that use both script and container actions, the container actions will run as sibling containers on the same network with the same volume mounts.
If you do not set a `container`, all steps will run directly on the host specified by `runs-on` unless a step refers to an action configured to run in a container.
**Example: Running a job within a container:**
```yaml
name: CI
on:
push:
branches: [ main ]
jobs:
container-test-job:
runs-on: ubuntu-latest
container:
image: node:18
env:
NODE_ENV: development
ports:
- 80
volumes:
- my_docker_volume:/volume_mount
options: --cpus 1
steps:
- name: Check for dockerenv file
run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv)
```
When you only specify a container image, you can omit the `image` keyword.
```yaml
jobs:
container-test-job:
runs-on: ubuntu-latest
container: node:18
```
##### `jobs.<job_id>.needs`
Use `jobs.<job_id>.needs` to identify any jobs that must complete successfully before this job will run. It can be a string or array of strings. If a job fails or is skipped, all jobs that need it are skipped unless the jobs use a conditional expression that causes the job to continue. If a run contains a series of jobs that need each other, a failure or skip applies to all jobs in the dependency chain from the point of failure or skip onwards. If you would like a job to run even if a job it is dependent on did not succeed, use the `always()` conditional expression in `jobs.<job_id>.if`.
**Example: Requiring successful dependent jobs:**
```yaml
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
```
##### `jobs.<job_id>.if`
You can use the `jobs.<job_id>.if` conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional.
When you use expressions in an `if` conditional, you can, optionally, omit the `${{ }}` expression syntax because GitHub Actions automatically evaluates the `if` conditional as an expression. However, this exception does not apply everywhere.
You must always use the `${{ }}` expression syntax or escape with `''`, `""`, or `()` when the expression starts with `!`, since `!` is reserved notation in [YAML](../files/YAML.md) format. For example:
```yaml
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}
```
For more information, see "Expressions."
##### `jobs.<job_id>.runs-on`
Use `jobs.<job_id>.runs-on` to define the type of machine to run the job on.
##### `jobs.<job_id>.env`
A `map` of variables that are available to all steps in the job. You can set variables for the entire workflow or an individual step.
##### `jobs.<job_id>.steps`
A job contains a sequence of tasks called `steps`. Steps can run commands, run setup tasks, or run an action in your repository, a public repository, or an action published in a [Docker](../tools/Docker.md) registry. Not all steps run actions, but all actions run as a step. Each step runs in its own process in the runner environment and has access to the workspace and filesystem. Because steps run in their own process, changes to [environment variables](../linux/Environment%20Variables.md) are not preserved between steps. [GitHub](GitHub.md) provides built-in steps to set up and complete a job.
**Example of `jobs.<job_id>.steps`:**
```yaml
name: Greeting from Mona
on: push
jobs:
my-job:
name: My Job
runs-on: ubuntu-latest
steps:
- name: Print a greeting
env:
MY_VAR: Hi there! My name is
FIRST_NAME: Mona
MIDDLE_NAME: The
LAST_NAME: Octocat
run: |
echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.
```
- `jobs.<job_id>.steps[*].if`
You can use the `if` conditional to prevent a step from running unless a condition is met. You can use any supported context and expression to create a conditional.
- `jobs.<job_id>.steps[*].name`
A name for your step to display on [GitHub](GitHub.md).
- `jobs.<job_id>.steps[*].uses`
Selects an action to run as part of a step in your job. An action is a reusable unit of code. You can use an action defined in the same repository as the workflow, a public repository, or in a published [Docker](../tools/Docker.md) container image.
Some actions require inputs that you must set using the `with` keyword. Review the action's README file to determine the inputs required.
**Example: Using versioned actions**
```yaml
steps:
# Reference a specific commit
- uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
# Reference the major version of a release
- uses: actions/checkout@v4
# Reference a specific version
- uses: actions/checkout@v4.2.0
# Reference a branch
- uses: actions/checkout@main
```
- `jobs.<job_id>.steps[*].run`
Runs command-line programs using the operating system's [shell](../applications/cli/Shell.md). If you do not provide a `name`, the step name will default to the text specified in the `run` command. Commands run using non-login shells by default.
Each `run` keyword represents a new process and [shell](../applications/cli/Shell.md) in the runner environment. When you provide multi-line commands, each line runs in the same [shell](../applications/cli/Shell.md). For example:
A single-line command:
```yaml
- name: Install Dependencies
run: npm install
```
A multi-line command:
```yaml
- name: Clean install dependencies and build
run: |
npm ci
npm run build
```
- `jobs.<job_id>.steps[*].working-directory`
Using the `working-directory` keyword, you can specify the working directory of where to run the command.
```yaml
- name: Clean temp directory
run: rm -rf *
working-directory: ./temp
```
- `jobs.<job_id>.steps[*].with`
A `map` of the input parameters defined by the action. Each input parameter is a key/value pair. Input parameters are set as [environment variables](../linux/Environment%20Variables.md). The variable is prefixed with `INPUT_` and converted to upper case.
Input parameters defined for a [Docker](../tools/Docker.md) container must use `args`. For more information, see "`jobs.<job_id>.steps[*].with.args`."
**Example of `jobs.<job_id>.steps[*].with`
Defines the three input parameters (`first_name`, `middle_name`, and `last_name`) defined by the `hello_world` action. These input variables will be accessible to the `hello-world` action as `INPUT_FIRST_NAME`, `INPUT_MIDDLE_NAME`, and `INPUT_LAST_NAME` [environment variables](../linux/Environment%20Variables.md).
```yaml
jobs:
my_first_job:
steps:
- name: My first step
uses: actions/hello_world@main
with:
first_name: Mona
middle_name: The
last_name: Octocat
```
- `jobs.<job_id>.steps[*].with.args`
A `string` that defines the inputs for a [Docker](../tools/Docker.md) container. [GitHub](GitHub.md) passes the `args` to the container's `ENTRYPOINT` when the container starts up. An `array of strings` is not supported by this parameter. A single argument that includes spaces should be surrounded by double quotes `""`.
- `jobs.<job_id>.steps[*].env`
Sets variables for steps to use in the runner environment. You can also set variables for the entire workflow or a job. For more information, see `env` and `jobs.<job_id>.env`.
When more than one environment variable is defined with the same name, [GitHub](GitHub.md) uses the most specific variable. For example, an environment variable defined in a step will override job and workflow [environment variables](../linux/Environment%20Variables.md) with the same name, while the step executes. An environment variable defined for a job will override a workflow variable with the same name, while the job executes.
Public actions may specify expected variables in the README file. If you are setting a secret or sensitive value, such as a password or token, you must set secrets using the `secrets` context.
**Example of `jobs.<job_id>.steps[*].env`**
```yaml
steps:
- name: My first action
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FIRST_NAME: Mona
LAST_NAME: Octocat
```
## Events
An event is a specific activity in a repository that triggers a workflow run. For example, activity can originate from [GitHub](GitHub.md) when someone creates a pull request, opens an issue, or pushes a commit to a repository. You can also trigger a workflow to run on a schedule, by posting to a REST API, or manually.
### `create`
Runs your workflow when someone creates a [Git](Git.md) reference ([Git](Git.md) branch or tag) in the workflow's repository.
For example, you can run a workflow when the `create` event occurs.
```yaml
on:
create
```
### `delete`
Runs your workflow when someone deletes a [Git](Git.md) reference ([Git](Git.md) branch or tag) in the workflow's repository.
For example, you can run a workflow when the `delete` event occurs.
```yaml
on:
delete
```
### `discussion`
Runs your workflow when a discussion in the workflow's repository is created or modified.
Activity Types:
- `created`
- `edited`
- `deleted`
- `transferred`
- `pinned`
- `unpinned`
- `labeled`
- `unlabeled`
- `locked`
- `unlocked`
- `category_changed`
- `answered`
- `unanswered`
For example, you can run a workflow when a discussion has been `created`, `edited`, or `answered`.
```yaml
on:
discussion:
types: [created, edited, answered]
```
### `discussion_comment`
Runs your workflow when a comment on a discussion in the workflow's repository is created or modified.
Activity Types:
- `created`
- `edited`
- `deleted`
For example, you can run a workflow when a discussion comment has been `created` or `deleted`.
```yaml
on:
discussion_comment:
types: [created, deleted]
```
### `fork`
Runs your workflow when someone forks a repository.
For example, you can run a workflow when the `fork` event occurs.
```yaml
on:
fork
```
### `issue_comment`
Runs your workflow when an issue or pull request comment is created, edited, or deleted.
Activity Types:
- `created`
- `edited`
- `deleted`
For example, you can run a workflow when an issue or pull request comment has been `created` or `deleted`.
```yaml
on:
issue_comment:
types: [created, deleted]
```
### `issues`
Runs your workflow when an issue in the workflow's repository is created or modified.
Activity Types:
- `opened`
- `edited`
- `deleted`
- `transferred`
- `pinned`
- `unpinned`
- `closed`
- `reopened`
- `assigned`
- `unassigned`
- `labeled`
- `unlabeled`
- `locked`
- `unlocked`
- `milestoned`
- `demilestoned`
For example, you can run a workflow when an issue has been `opened`, `edited`, or `milestoned`.
```yaml
on:
issues:
types: [opened, edited, milestoned]
```
### `milestone`
Runs your workflow when a milestone in the workflow's repository is created or modified.
Activity Types:
- `created`
- `closed`
- `opened`
- `edited`
- `deleted`
For example, you can run a workflow when a milestone has been `opened` or `deleted`.
```yaml
on:
milestone:
types: [opened, deleted]
```
### `pull_request`
Runs your workflow when activity on a pull request in the workflow's repository occurs. For example, if no activity types are specified, the workflow runs when a pull request is opened or reopened or when the head branch of the pull request is updated.
Activity Types:
- `assigned`
- `unassigned`
- `labeled`
- `unlabeled`
- `opened`
- `edited`
- `closed`
- `reopened`
- `synchronize`
- `converted_to_draft`
- `ready_for_review`
- `locked`
- `unlocked`
- `milestoned`
- `demilestoned`
- `review_requested`
- `review_request_removed`
- `auto_merge_enabled`
- `auto_merge_disabled`
For example, you can run a workflow when a pull request has been opened or reopened.
```yaml
on:
pull_request:
types: [opened, reopened]
```
### `push`
Runs your workflow when you push a commit or tag, or when you create a repository from a template.
You can use the `branches` or `branches-ignore` filter to configure your workflow to only run when specific branches are pushed.
You can use the `tags` or `tags-ignore` filter to configure your workflow to only run when specific tags are pushed.
If you use both the `branches` filter and the `paths` filter, the workflow will only run when both filters are satisfied. For example, the following workflow will only run when a push that includes a change to a JavaScript (`.js`) file is made to a branch whose name starts with `releases/`:
```yaml
on:
push:
branches:
- 'releases/**'
paths:
- '**.js'
```
For example, you can run a workflow when the `push` event occurs.
```yaml
on:
push
```
### `release`
Runs your workflow when release activity in your repository occurs.
Activity Types:
- `published`
- `unpublished`
- `created`
- `edited`
- `deleted`
- `prereleased`
- `released`
For example, you can run a workflow when a release has been `published`.
```yaml
on:
release:
types: [published]
```
### `schedule`
The `schedule` event allows you to trigger a workflow at a scheduled time.
You can schedule a workflow to run at specific UTC times using POSIX cron syntax. Scheduled workflows run on the latest commit on the default or base branch. The shortest interval you can run scheduled workflows is once every 5 minutes. A single workflow can be triggered by multiple `schedule` events. You can access the schedule event that triggered the workflow through the `github.event.schedule` context.
This example triggers the workflow every day at 5:30 and 17:30 UTC:
```yaml
on:
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '30 5,17 * * *'
```
### `workflow_dispatch`
To enable a workflow to be triggered manually, you need to configure the `workflow_dispatch` event. You can manually trigger a workflow run using the [GitHub](GitHub.md) API, [GitHub](GitHub.md) CLI, or [GitHub](GitHub.md) browser interface.
```yaml
on: workflow_dispatch
```
## Jobs
A job is a set of _steps_ in a workflow that is executed on the same runner. Each step is either a [shell](../applications/cli/Shell.md) script that will be executed, or an _action_ that will be run. Steps are executed in order and are dependent on each other. Since each step is executed on the same runner, you can share data from one step to another. For example, you can have a step that builds your application followed by a step that tests the application that was built.
You can configure a job's dependencies with other jobs; by default, jobs have no dependencies and run in parallel with each other. When a job takes a dependency on another job, it will wait for the dependent job to complete before it can run. For example, you may have multiple build jobs for different architectures that have no dependencies, and a packaging job that is dependent on those jobs. The build jobs will run in parallel, and when they have all completed successfully, the packaging job will run.
## Actions
An _action_ is a custom application for the GitHub Actions platform that performs a complex but frequently repeated task. Use an action to help reduce the amount of repetitive code that you write in your workflow files. An action can pull your [git](Git.md) repository from [GitHub](GitHub.md), set up the correct toolchain for your build environment, or set up the authentication to your cloud provider.
You can write your own actions, or you can find actions to use in your workflows in the GitHub Marketplace.

View file

@ -0,0 +1,43 @@
---
obj: concept
website: https://tailwindcss.com
---
# Tailwind CSS
Tailwind CSS is a utility-first CSS framework that provides a set of low-level utility classes to build designs directly in your markup. It's a highly customizable and efficient way to create modern, responsive user interfaces.
## Setup
To use TailwindCSS include this in your documents header:
```html
<script src="https://cdn.tailwindcss.com"></script>
```
## Modifiers
You can modify when a utility class will become active by using `mod:` before the class name.
Some modifiers include:
- `hover`
- `focus`
- `active`
- `disabled`
- `invalid`
- `first`
- `last`
- `even`
- `odd`
This modifier is used for dark mode:
- `dark`
These modifers are used for device orientation:
- `landscape`
- `portrait`
These modifers are used for responsive design and reresent their respective screen sizes when a class will become active:
- `sm`
- `md`
- `lg`
- `xl`
- `2xl`
For a list of all classes see the [documentation](https://tailwindcss.com/docs).

View file

@ -0,0 +1,10 @@
---
website: https://godotengine.org/
repo: https://github.com/godotengine/godot
obj: application
flatpak-id: org.godotengine.Godot
---
# Godot Game Engine
#wip #🐇 #notnow
-> https://kidscancode.org/godot_recipes/4.x/

View file

@ -0,0 +1,9 @@
---
obj: concept
website: https://www.sqlite.org/index.html
---
# SQLite
SQLite is a C-language library that implements a small, fast, self-contained, high-reliability, full-featured, [SQL](languages/SQL.md) database engine. SQLite is the most used database engine in the world. SQLite is built into all mobile phones and most computers and comes bundled inside countless other applications that people use every day.
SQLite is an embedded [SQL](languages/SQL.md) database engine. Unlike most other [SQL](languages/SQL.md) databases, SQLite does not have a separate server process. SQLite reads and writes directly to ordinary disk files. A complete [SQL](languages/SQL.md) database with multiple tables, indices, triggers, and views, is contained in a single disk file. The database file format is cross-platform - you can freely copy a database between 32-bit and 64-bit systems or between big-endian and little-endian architectures. These features make SQLite a popular choice as an Application File Format.

View file

@ -0,0 +1,9 @@
---
obj: concept
wiki: https://en.wikipedia.org/wiki/Flutter_(software)
website: https://flutter.dev
repo: https://github.com/flutter/flutter
---
# Flutter
#wip #🐇 #notnow

View file

@ -0,0 +1,9 @@
---
website: https://www.python.org
obj: application
---
# Python
Python is an interpreted programming language.
#wip #🐇 #notnow

View file

@ -0,0 +1,701 @@
---
website: https://www.rust-lang.org
source: https://doc.rust-lang.org/book
obj: application
---
# Rust
[Rust](https://www.rust-lang.org/) is a statically-typed programming language known for its emphasis on performance, safety, and concurrency. Originally developed by [Mozilla](../../../internet/websites/clearnet/Mozilla.md), Rust has gained popularity for its ability to provide low-level control over system resources without sacrificing memory safety. Rust uses [Cargo](../../../applications/development/cargo.md) as its package manager and build tool.
## Syntax
Your application starts within the main function, so the simplest application is this:
```rust
fn main() {
}
```
### Variables
You can declare variables. Variables are immutable by default, if you need to change them you have to use the `mut` keyword. Every variable is strongly typed, but you can either ommit type information and let the compiler infer the type or explicitly state it. Constants which never change can be made as well.
```rust
let var = "Hello";
let mut mutable = "World";
let explicit_num: isize = 0;
const NINE_K: isize = 9000;
```
### Data Types & Ownership
Every variable in Rust is strongly typed. You can define your own types and use the compiler together with an algebraic type system to your advantage.
In Rust, primitive types are classified into two categories: scalar types and compound types:
#### Scalar Types
1. **Integers:**
- `i8`: Signed 8-bit integer
- `i16`: Signed 16-bit integer
- `i32`: Signed 32-bit integer
- `i64`: Signed 64-bit integer
- `i128`: Signed 128-bit integer
- `u8`: Unsigned 8-bit integer
- `u16`: Unsigned 16-bit integer
- `u32`: Unsigned 32-bit integer
- `u64`: Unsigned 64-bit integer
- `u128`: Unsigned 128-bit integer
- `isize`: Platform-dependent signed integer
- `usize`: Platform-dependent unsigned integer
2. **Floating-point:**
- `f32`: 32-bit floating-point number
- `f64`: 64-bit floating-point number
3. **Characters:**
- `char`: A [Unicode](../../../files/Unicode.md) character (4 bytes)
4. **Booleans:**
- `bool`: Boolean type representing either `true` or `false`
#### Compound Types
1. **Arrays:**
- `[T; N]`: Fixed-size array of elements of type `T` and length `N`
2. **Tuples:**
- `(T1, T2, ..., Tn)`: Heterogeneous collection of elements of different types
#### Pointer Types
1. **References:**
- `&T`: Immutable reference
- `&mut T`: Mutable reference
2. **Raw Pointers:**
- `*const T`: Raw immutable pointer
- `*mut T`: Raw mutable pointer
Rust enforces some rules on variables in order to be memory safe. So there are three kinds of variables you could have:
- Owned Variable `T`: You are the owner of this variable with data type `T`
- Reference `&T`: You have a read only reference of the variables content
- Mutable Reference `&mut T`: You have a modifiable reference to the variable
> Note: If a function does not need to mutate or own a variable, consider using a reference
### Conditionals
Conditionals like `if` and `match` can be used, while `match` can do more powerful pattern matching than `if`.
```rust
let age = 20;
if age > 18 {
println!("Adult");
} else if age == 18 {
println!("Exactly 18");
} else {
println!("Minor");
}
match age {
18 => println!("Exactly 18"),
_ => println!("Everything else")
}
```
### Loops
There are three types of loops.
```rust
loop {
println!("Going on until time ends");
}
for item in list {
println!("This is {item}");
}
while condition {
println!("While loop");
}
```
### Functions
One can use functions with optional arguments and return types. If you `return` on the last line, you can ommit the `return` keyword and `;` to return the value.
```rust
fn printHello() {
println!("Hello");
}
fn greet(name: &str) {
println!("Hello {name}");
}
fn add_two(a: isize) -> isize {
a + 2 // same as "return a + 2;"
}
```
### Enums
Rust has enums which can even hold some data.
```rust
enum StatusCode {
NOT_FOUND,
OK,
Err(String)
}
let err_response = StatusCode::Err(String::from("Internal Error"));
match err_response {
StatusCode::Ok => println!("Everything is fine"),
StatusCode::NOT_FOUND => println!("Not found");
StatusCode::Err(err) => println!("Some error: {err}"); // will print "Some error: Internal Error"
}
// other way to pattern match for a single pattern
if let StatusCode::Err(msg) = err_response {
println!("{msg}!");
}
```
### Structs
Rust has some object-oriented features like structs.
```rust
struct Person {
first_name: String,
age: isize
}
impl Person {
fn new(first_name: &str) -> Self {
Self {
first_name: first_name.to_string(),
age: 0
}
}
fn greet(&self) {
println!("Hello {}", self.first_name);
}
fn get_older(&mut self) {
self.age += 1;
}
}
```
### Comments
Rust has support for comments. There are regular comments, multiline comments and documentation comments. Documentation comments get used when generating documation via `cargo doc` and inside the IDE.
```rust
// This is a comment
/*
This
is multiline
comment
*/
/// This function does something.
/// Documentation comments can be styled with markdown as well.
///
/// # Example
///
/// If you place a rust code block here, you can provide examples on how to use this function and `cargo test` will automatically run this code block when testing.
fn do_something() {
}
```
### Modules
You can split your code up into multiple modules for better organization.
```rust
// will search for `mymod.rs` or `mymod/mod.rs` beside the source file and include it as `mymod`;
mod mymod;
// inline module
mod processor {
struct AMD {
name: String
}
}
fn main() {
// full syntax
let proc = processor::AMD{ name: "Ryzen".to_string() };
// you can put often used symbols in scope
use processor::AMD;
let proc = AMD{ name: "Ryzen".to_string() };
}
```
### Generics
Generics let you write code for multiple data types without repeating yourself. Instead of an explicit data type, you write your code around a generic type.
```rust
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
// you can declare methods which only work for specific data types.
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
impl<X1, Y1> Point<X1, Y1> {
// define generic types on functions
fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
Point {
x: self.x,
y: other.y,
}
}
}
enum Option<T> {
Some(T),
None,
}
// you can have multiple generic types
enum Result<T, E> {
Ok(T),
Err(E),
}
```
### Traits
Traits let you define shared behavior on structs. You define what methods a struct should have and it is up the the struct to implement them.
```rust
pub trait Summary {
fn summarize(&self) -> String;
}
// you can define default behaviour
pub trait DefaultSummary {
fn summarize(&self) -> String {
String::from("(Read more...)")
}
}
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
// use traits as parameters
pub fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
// you can also restrict generic types to only ones that implement certain traits
pub fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}
// even multiple at once
pub fn notify<T: Summary + Display>(item: &T) {}
// another way to restrict types to traits
fn some_function<T, U>(t: &T, u: &U) -> i32
where
T: Display + Clone,
U: Clone + Debug,
{}
// you can restrict at impl level too
struct Pair<T> {
x: T,
y: T,
}
impl<T> Pair<T> {
fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl<T: Display + PartialOrd> Pair<T> {
// this function is only available if T has Display and PartialOrd
fn cmp_display(&self) {
if self.x >= self.y {
println!("The largest member is x = {}", self.x);
} else {
println!("The largest member is y = {}", self.y);
}
}
}
```
Common traits you can implement on your types are:
- `Clone`: Allows creating a duplicate of an object.
```rust
pub trait Clone {
fn clone(&self) -> Self;
}
```
- `Copy`: Types that can be copied by simple bitwise copying.
```rust
pub trait Copy: Clone {}
```
- `Debug`: Enables formatting a value for debugging purposes.
```rust
pub trait Debug {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
```
- `Default`: Provides a default value for a type.
```rust
pub trait Default {
fn default() -> Self;
}
```
- `Eq` and `PartialEq`: Enables equality comparisons.
```rust
pub trait Eq: PartialEq<Self> {}
pub trait PartialEq<Rhs: ?Sized = Self> {
fn eq(&self, other: &Rhs) -> bool;
}
```
- `Ord` and `PartialOrd`: Enables ordering comparisons.
```rust
pub trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
}
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
}
```
- `Iterator`: Represents a sequence of values.
```rust
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
// Other iterator methods...
}
```
- `Read` and `Write`: For reading from and writing to a byte stream.
```rust
pub trait Read {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
}
pub trait Write {
fn write(&mut self, buf: &[u8]) -> Result<usize, Error>;
}
```
- `Fn`, `FnMut`, and `FnOnce`: Traits for function types with different levels of mutability.
```rust
pub trait Fn<Args> {
// function signature
}
pub trait FnMut<Args>: Fn<Args> {
// function signature
}
pub trait FnOnce<Args>: FnMut<Args> {
// function signature
}
```
- `Drop`: Specifies what happens when a value goes out of scope.
```rust
pub trait Drop {
fn drop(&mut self);
}
```
- `Deref` and `DerefMut`: Used for overloading dereference operators.
```rust
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
pub trait DerefMut: Deref {
fn deref_mut(&mut self) -> &mut Self::Target;
}
```
- `AsRef` and `AsMut`: Allows types to be used as references.
```rust
pub trait AsRef<T: ?Sized> {
fn as_ref(&self) -> &T;
}
pub trait AsMut<T: ?Sized>: AsRef<T> {
fn as_mut(&mut self) -> &mut T;
}
```
- `Index` and `IndexMut`: Enables indexing into a data structure.
```rust
pub trait Index<Idx: ?Sized> {
type Output: ?Sized;
fn index(&self, index: Idx) -> &Self::Output;
}
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}
```
- `Send` and `Sync`: Indicate whether a type is safe to be transferred between threads (Send) or shared between threads (Sync).
```rust
unsafe trait Send {}
unsafe trait Sync {}
```
- `Into` and `From`: Facilitates conversions between types.
```rust
pub trait Into<T> {
fn into(self) -> T;
}
pub trait From<T> {
fn from(T) -> Self;
}
```
- `Display`: Formatting values for user display.
```rust
pub trait Display {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
```
- `FromStr` and `ToString`: Enables conversion between strings and other types.
```rust
pub trait FromStr {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
pub trait ToString {
fn to_string(&self) -> String;
}
```
- `Error`: Represents errors that can occur during the execution of a program.
```rust
pub trait Error: Debug {
fn source(&self) -> Option<&(dyn Error + 'static)>;
}
```
- `Add`, `Sub`, `Mul`, and `Div`: Traits for arithmetic operations.
```rust
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
// Similar traits for Sub, Mul, and Div
```
### Closures
Closures are anonymous functions. They can be assigned to variables, passed as parameters or returned from a function.
```rust
fn add_one_v1 (x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1 ;
// this function takes ownership over variables it uses as noted by `move`
thread::spawn(
move || println!("From thread: {:?}", list)
).join().unwrap();
// To use closures as parameters, specify the type. It is one of the Fn traits
impl<T> Option<T> {
pub fn unwrap_or_else<F>(self, f: F) -> T
where
F: FnOnce() -> T
{
match self {
Some(x) => x,
None => f(),
}
}
}
```
### Iterators
The [iterator pattern](../patterns/behavioral/Iterator%20Pattern.md) allows you to perform some task on a sequence of items in turn. An iterator is responsible for the logic of iterating over each item and determining when the sequence has finished. When you use iterators, you dont have to reimplement that logic yourself.
```rust
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
```
With this you can do functional programming with the iterators.
Some functions on them include:
- `chain(other)`: An iterator that links two iterators together, in a chain.
- `cloned()`: An iterator that clones the elements of an underlying iterator.
- `copied()`: An iterator that copies the elements of an underlying iterator.
- `cycle()`: An iterator that repeats endlessly.
- `empty()`: An iterator that yields nothing.
- `enumerate()`: An iterator that yields the current count and the element during iteration.
- `filter(predicate)`: An iterator that filters the elements of `iter` with `predicate`.
- `filterMap(f)`: An iterator that uses `f` to both filter and map elements from `iter`.
- `flat_map(f)`: An iterator that maps each element to an iterator, and yields the elements of the produced iterators.
- `flatten()`: An iterator that flattens one level of nesting in an iterator of things that can be turned into iterators.
- `from_fn(f)`: An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
- `fuse()`: An iterator that yields `None` forever after the underlying iterator yields `None` once.
- `inspect(f)`: An iterator that calls a function with a reference to each element before yielding it.
- `map(f)`: An iterator that maps the values of `iter` with `f`.
- `map_while(f)`: An iterator that only accepts elements while `predicate` returns `Some(_)`.
- `once(value)`: An iterator that yields an element exactly once.
- `peekable()`: An iterator with a `peek()` that returns an optional reference to the next element.
- `repeat(value)`: An iterator that repeats an element endlessly.
- `rev()`: A double-ended iterator with the direction inverted.
- `skip(n)`: An iterator that skips over `n` elements of `iter`.
- `skip_while(f)`: An iterator that rejects elements while `predicate` returns `true`.
- `step_by(n)`: An iterator for stepping iterators by a custom amount.
- `successors(first, f)`: A new iterator where each successive item is computed based on the preceding one.
- `take(n)`: An iterator that only iterates over the first `n` iterations of `iter`.
- `take_while(f)`: An iterator that only accepts elements while `predicate` returns `true`.
- `zip(a, b)`: An iterator that iterates two other iterators simultaneously.
### Standard Library
Rust, a systems programming language known for its focus on safety and performance, comes with a rich standard library that provides a wide range of modules to handle common tasks.
1. **`std::collections`**: Data structures like `Vec`, `HashMap`, etc.
2. **`std::fs`**: File system manipulation and I/O operations.
3. **`std::thread`**: Facilities for concurrent programming with threads.
4. **`std::time`**: Time-related types and functionality.
5. **`std::io`**: Input and output facilities.
6. **`std::path`**: Path manipulation utilities.
7. **`std::env`**: Interface to the environment, command-line arguments, etc.
9. **`std::string`**: String manipulation utilities.
10. **`std::cmp`**: Comparison traits and functions.
11. **`std::fmt`**: Formatting traits and utilities.
12. **`std::result`**: Result type and related functions.
13. **`std::error`**: Error handling utilities.
14. **`std::sync`**: Synchronization primitives.
15. **`std::net`**: Networking functionality.
16. **`std::num`**: Numeric types and operations.
17. **`std::char`**: Character manipulation utilities.
18. **`std::mem`**: Memory manipulation utilities.
19. **`std::slice`**: Slice manipulation operations.
20. **`std::marker`**: Marker traits for influencing Rust's type system.
## Macros
Weve used macros like `println!` before, but we havent fully explored what a macro is and how it works. The term _macro_ refers to a family of features in Rust: _declarative_ macros with `macro_rules!` and three kinds of _procedural_ macros:
- Custom `#[derive]` macros that specify code added with the `derive` attribute used on structs and enums
- Attribute-like macros that define custom attributes usable on any item
- Function-like macros that look like function calls but operate on the tokens specified as their argument
Fundamentally, macros are a way of writing code that writes other code, which is known as _metaprogramming_. All of these macros _expand_ to produce more code than the code youve written manually.
Declarative macros work almost like a `match` statement.
```rust
macro_rules! mymacro {
($expression:expr) => {
println!("{}", $expression)
};
($expression:expr, $other:expr) => {
println!("{} {}", $expression, $other)
};
}
mymacro!("Hello World");
mymacro!("Hello", "World");
```
This macro gets expanded to the code inside the `macro_rules!` section with the provided arguments. For more information on macros, see the [docs](https://doc.rust-lang.org/reference/macros-by-example.html).
## [Crates](https://lib.rs/)
- [anyhow](https://lib.rs/crates/anyhow): Flexible concrete Error type built on `std::error::Error`
- [itertools](https://lib.rs/crates/itertools): Extra iterator adaptors, iterator methods, free functions, and macros
- [num_enum](https://lib.rs/crates/num_enum): Procedural macros to make inter-operation between primitives and enums easier
### Encoding
- [bincode](https://lib.rs/crates/bincode): A binary serialization / deserialization strategy for transforming structs into bytes and vice versa!
- [serde](https://lib.rs/crates/serde): A generic serialization/deserialization framework
- [serde_json](https://lib.rs/crates/serde_json): A [JSON](../../../files/JSON.md) serialization file format
- [serde_yaml](https://lib.rs/crates/serde_yaml): [YAML](../../../files/YAML.md) data format for Serde
- [bson](https://lib.rs/crates/bson): Encoding and decoding support for [BSON](../../../files/BSON.md) in Rust
- [hex](https://lib.rs/crates/hex): Encoding and decoding data into/from hexadecimal representation
- [toml](https://lib.rs/crates/toml): A native Rust encoder and decoder of [TOML](../../../files/TOML.md)-formatted files and streams.
- [base64](https://lib.rs/crates/base64): encodes and decodes [base64](../../../files/Base64.md) as bytes or utf8
### Algorithms
- [rand](https://lib.rs/crates/rand): Random number generators and other randomness functionality
### Debugging
- [log](https://lib.rs/crates/log): A lightweight logging facade for Rust
- [env_logger](https://lib.rs/crates/env_logger): A logging implementation for `log` which is configured via an environment variable
### Mail
- [lettre](https://lib.rs/crates/lettre): [Email](../../../internet/eMail.md) client
### Visualization
- [plotters](https://lib.rs/crates/plotters): A Rust drawing library focus on data plotting for both WASM and native applications
- [plotly](https://lib.rs/crates/plotly): A plotting library powered by Plotly.js
- [textplot](https://lib.rs/crates/textplots): Terminal plotting library
### Templates
- [maud](https://lib.rs/crates/maud): Compile-time [HTML](../../../internet/HTML.md) templates
- [tera](https://lib.rs/crates/tera): Template engine based on [Jinja](../../../tools/Jinja.md) templates
### Media
- [image](https://lib.rs/crates/image): Imaging library. Provides basic image processing and encoders/decoders for common image formats.
### CLI
- [rustyline](https://lib.rs/crates/rustyline): Rustyline, a readline implementation based on Antirez's Linenoise
- [clap](https://lib.rs/crates/clap): A simple to use, efficient, and full-featured Command Line Argument Parser
- [crossterm](https://lib.rs/crates/crossterm): A crossplatform terminal library for manipulating terminals
- [indicatif](https://lib.rs/crates/indicatif): A progress bar and cli reporting library for Rust
- [argh](https://lib.rs/crates/argh): Derive-based argument parser optimized for code size
- [owo-colors](https://lib.rs/crates/owo-colors): Zero-allocation terminal colors that'll make people go owo
- [yansi](https://lib.rs/crates/yansi): A dead simple ANSI terminal color painting library
### Compression
- [flate2](https://lib.rs/crates/flate2): DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams.
- [tar](https://lib.rs/crates/tar): A Rust implementation of a [TAR](../../../applications/cli/compression/tar.md) file reader and writer.
- [zstd](https://lib.rs/crates/zstd): Binding for the zstd compression library
- [unrar](https://lib.rs/crates/unrar): list and extract RAR archives
### Databases
- [rusqlite](https://lib.rs/crates/rusqlite): Ergonomic wrapper for [SQLite](../SQLite.md)
- [sqlx](https://lib.rs/crates/sqlx): The Rust [SQL](SQL.md) Toolkit. An async, pure Rust [SQL](SQL.md) crate featuring compile-time checked queries without a DSL. Supports PostgreSQL, MySQL, and [SQLite](../SQLite.md).
- [mongodb](https://lib.rs/crates/mongodb): The official [MongoDB](../../../applications/development/MongoDB.md) driver for Rust
### Data and Time
- [chrono](https://lib.rs/crates/chrono): Date and time library for Rust
- [humantime](https://lib.rs/crates/humantime): A parser and formatter for `std::time::{Duration, SystemTime}`
### HTTP
- [hyper](https://lib.rs/crates/hyper): A fast and correct [HTTP](../../../internet/HTTP.md) library
- [reqwest](https://lib.rs/crates/reqwest): higher level [HTTP](../../../internet/HTTP.md) client library
- [actix-web](https://lib.rs/crates/actix-web): Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust
### Text
- [regex](https://lib.rs/crates/regex): An implementation of [regular expressions](../../../tools/Regex.md) for Rust. This implementation uses finite automata and guarantees linear time matching on all inputs.
- [comfy-table](https://lib.rs/crates/comfy-table): An easy to use library for building beautiful tables with automatic content wrapping
- [similar](https://lib.rs/crates/similar): A diff library for Rust
### Concurrency
- [parking_lot](https://lib.rs/crates/parking_lot): More compact and efficient implementations of the standard synchronization primitives
- [crossbeam](https://lib.rs/crates/crossbeam): Tools for concurrent programming
- [rayon](https://lib.rs/crates/rayon): Simple work-stealing parallelism for Rust
### Async
- [tokio](https://lib.rs/crates/tokio): An event-driven, non-blocking I/O platform for writing asynchronous I/O backed applications
- [futures](https://lib.rs/crates/futures): An implementation of futures and streams featuring zero allocations, composability, and iterator-like interfaces

View file

@ -0,0 +1,685 @@
---
obj: concept
---
# SQL
Structured Query Language (SQL) is a powerful and standardized programming language used for managing and manipulating relational databases. It allows users to interact with databases to create, retrieve, update, and delete data, as well as define and modify the database schema. SQL is widely used in web development, data analysis, and various other domains where data storage and retrieval are essential.
A database most often contains one or more tables. Each table is identified by a name (e.g. "Customers" or "Orders"). Tables contain records (rows) with data.
# SQL Statements
Most of the actions you need to perform on a database are done with SQL statements.
Example:
```sql
SELECT * FROM Customers;
```
### Comments
Comments are used to explain sections of SQL statements, or to prevent execution of SQL statements.
Single Line Comments:
```sql
--Select all:
SELECT * FROM Customers;
```
Multi Line comments:
```sql
/*Select all the columns
of all the records
in the Customers table:*/
SELECT * FROM Customers;
```
## SELECT
The `SELECT` statement is used to select data from a database.
Select:
```sql
SELECT column1, column2, ...
FROM table_name;
```
Select all:
```sql
SELECT * FROM table
```
### SELECT DISTINC
The `SELECT DISTINCT` statement is used to return only distinct (different) values.
```sql
SELECT DISTINCT Country FROM Customers;
SELECT COUNT(DISTINCT Country) FROM Customers;
```
## WHERE
The `WHERE` clause is used to filter records.
```sql
SELECT column1, column2, ...
FROM table_name
WHERE condition;
```
```sql
SELECT * FROM Customers
WHERE Country='Mexico';
```
```sql
SELECT * FROM Customers
WHERE CustomerID=1;
```
The following operators can be used in the `WHERE` clause:
| Operator | Description |
| -------- | ------------------------------------------------------------------------------- |
| = | Equal |
| > | Greater than |
| < | Less than |
| >= | Greater than or equal |
| <= | Less than or equal |
| <> | Not equal. **Note:** In some versions of SQL this operator may be written as != |
| BETWEEN | Between a certain range |
| LIKE | Search for a pattern |
| IN | To specify multiple possible values for a column |
### LIKE
The `LIKE` operator is used in a `WHERE` clause to search for a specified pattern in a column.
There are two wildcards often used in conjunction with the `LIKE` operator:
-  The percent sign `%` represents zero, one, or multiple characters
-  The underscore sign `_` represents one, single character
```sql
SELECT column1, column2, ...
FROM table_name
WHERE columnN LIKE pattern;
```
#### The _ Wildcard
The `_` wildcard represents a single character.
It can be any character or number, but each `_` represents one, and only one, character.
```sql
SELECT * FROM Customers
WHERE city LIKE 'L_nd__';
```
#### The % Wildcard
The `%` wildcard represents any number of characters, even zero characters.
```sql
SELECT * FROM Customers
WHERE city LIKE '%L%';
```
#### Starts With
```sql
SELECT * FROM Customers
WHERE CustomerName LIKE 'La%';
```
#### Ends With
```sql
SELECT * FROM Customers
WHERE CustomerName LIKE '%a';
```
#### Contains
```sql
SELECT * FROM Customers
WHERE CustomerName LIKE '%or%';
```
### IN
The `IN` operator allows you to specify multiple values in a `WHERE` clause.
The `IN` operator is a shorthand for multiple `OR` conditions.
```sql
SELECT * FROM Customers
WHERE Country IN ('Germany', 'France', 'UK');
```
Subquery:
```sql
SELECT * FROM Customers
WHERE CustomerID NOT IN (SELECT CustomerID FROM Orders);
```
### BETWEEN
The `BETWEEN` operator selects values within a given range. The values can be numbers, text, or dates.
The `BETWEEN` operator is inclusive: begin and end values are included.
```sql
SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN value1 AND value2;
SELECT * FROM Orders
WHERE OrderDate BETWEEN '1996-07-01' AND '1996-07-31';
```
### AND
The `WHERE` clause can contain one or many `AND` operators.
```sql
SELECT *
FROM Customers
WHERE Country = 'Spain' AND CustomerName LIKE 'G%';
```
### OR
The `WHERE` clause can contain one or more `OR` operators.
```sql
SELECT *
FROM Customers
WHERE Country = 'Germany' OR Country = 'Spain';
```
### Combine AND & OR
```sql
SELECT * FROM Customers
WHERE Country = 'Spain' AND (CustomerName LIKE 'G%' OR CustomerName LIKE 'R%');
```
### NOT
The `NOT` operator is used in combination with other operators to give the opposite result, also called the negative result.
```sql
SELECT * FROM Customers
WHERE NOT Country = 'Spain';
SELECT * FROM Customers
WHERE City NOT IN ('Paris', 'London');
```
## ORDER BY
The `ORDER BY` keyword is used to sort the result-set in ascending or descending order.
The `ORDER BY` keyword sorts the records in ascending order by default. To sort the records in descending order, use the `DESC` keyword.
```sql
SELECT column1, column2, ...
FROM table_name
ORDER BY column1, column2, ... ASC|DESC;
```
## INSERT INTO
The `INSERT INTO` statement is used to insert new records in a table.
Example:
```sql
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
```
Insert Many:
```sql
INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
VALUES
('Cardinal', 'Tom B. Erichsen', 'Skagen 21', 'Stavanger', '4006', 'Norway'),
('Greasy Burger', 'Per Olsen', 'Gateveien 15', 'Sandnes', '4306', 'Norway'),
('Tasty Tee', 'Finn Egan', 'Streetroad 19B', 'Liverpool', 'L1 0AA', 'UK');
```
## UPDATE
The `UPDATE` statement is used to modify the existing records in a table.
```sql
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
```
## DELETE
The `DELETE` statement is used to delete existing records in a table.
Example:
```sql
DELETE FROM table_name WHERE condition;
```
Delete All:
```sql
DELETE FROM table_name;
```
Delete Table:
```sql
DROP TABLE table_name;
```
## LIMIT
The `LIMIT` clause is used to specify the number of records to return.
```sql
SELECT * FROM Customers
LIMIT 3;
```
## Aliases
SQL aliases are used to give a table, or a column in a table, a temporary name.
Aliases are often used to make column names more readable.
An alias only exists for the duration of that query.
An alias is created with the `AS` keyword.
```sql
SELECT column_name AS alias_name
FROM table_name;
```
## JOIN
A `JOIN` clause is used to combine rows from two or more tables, based on a related column between them.
### INNER JOIN
The `INNER JOIN` keyword selects records that have matching values in both tables.
```sql
SELECT Orders.OrderID, Customers.CustomerName
FROM Orders
INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID;
```
# Database
## Create Database
The `CREATE DATABASE` statement is used to create a new SQL database.
```sql
CREATE DATABASE databasename;
```
## Delete Database
The `DROP DATABASE` statement is used to drop an existing SQL database.
```sql
DROP DATABASE databasename;
```
## Create Table
The `CREATE TABLE` statement is used to create a new table in a database.
```sql
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype,
....
);
CREATE TABLE Persons (
PersonID int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);
```
## Delete Table
The `DROP TABLE` statement is used to drop an existing table in a database.
```sql
DROP TABLE table_name;
```
## Change Table
The `ALTER TABLE` statement is used to add, delete, or modify columns in an existing table.
The `ALTER TABLE` statement is also used to add and drop various constraints on an existing table.
Add Column:
```sql
ALTER TABLE Customers
ADD Email varchar(255);
```
Drop Column:
```sql
ALTER TABLE Customers
DROP COLUMN Email;
```
Rename Column:
```sql
ALTER TABLE table_name
RENAME COLUMN old_name to new_name;
```
Change Datatype:
```sql
ALTER TABLE Persons
ALTER COLUMN DateOfBirth year;
```
## Constraints
Constraints can be specified when the table is created with the `CREATE TABLE` statement, or after the table is created with the `ALTER TABLE` statement.
```sql
CREATE TABLE table_name (
column1 datatype constraint,
column2 datatype constraint,
column3 datatype constraint,
....
);
```
The following constraints are commonly used in SQL:
### NOT NULL
By default, a column can hold NULL values.
The `NOT NULL` constraint enforces a column to NOT accept NULL values.
This enforces a field to always contain a value, which means that you cannot insert a new record, or update a record without adding a value to this field.
```sql
CREATE TABLE Persons (
    ID int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255) NOT NULL,
    Age int
);
```
### UNIQUE
The `UNIQUE` constraint ensures that all values in a column are different.
Both the `UNIQUE` and `PRIMARY KEY` constraints provide a guarantee for uniqueness for a column or set of columns.
A `PRIMARY KEY` constraint automatically has a `UNIQUE` constraint.
However, you can have many `UNIQUE` constraints per table, but only one `PRIMARY KEY` constraint per table.
### PRIMARY KEY
The `PRIMARY KEY` constraint uniquely identifies each record in a table.
Primary keys must contain UNIQUE values, and cannot contain NULL values.
A table can have only ONE primary key; and in the table, this primary key can consist of single or multiple columns (fields).
```sql
CREATE TABLE Persons (
ID int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int,
PRIMARY KEY (ID)
);
```
### FOREIGN KEY
The `FOREIGN KEY` constraint is used to prevent actions that would destroy links between tables.
A `FOREIGN KEY` is a field (or collection of fields) in one table, that refers to the `PRIMARY KEY` in another table.
The table with the foreign key is called the child table, and the table with the primary key is called the referenced or parent table.
```sql
CREATE TABLE Orders (
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
```
### CHECK
The `CHECK` constraint is used to limit the value range that can be placed in a column.
If you define a `CHECK` constraint on a column it will allow only certain values for this column.
If you define a `CHECK` constraint on a table it can limit the values in certain columns based on values in other columns in the row.
```sql
CREATE TABLE Persons (
    ID int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int,
    CHECK (Age>=18)
);
```
### DEFAULT
The `DEFAULT` constraint is used to set a default value for a column.
The default value will be added to all new records, if no other value is specified.
```sql
CREATE TABLE Orders (
    ID int NOT NULL,
    OrderNumber int NOT NULL,
    OrderDate date DEFAULT GETDATE()
);
```
### AUTO_INCREMENT
Auto-increment allows a unique number to be generated automatically when a new record is inserted into a table.
Often this is the primary key field that we would like to be created automatically every time a new record is inserted.
```sql
CREATE TABLE Persons (
    Personid int NOT NULL AUTO_INCREMENT,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int,
    PRIMARY KEY (Personid)
);
```
## Create Index
The `CREATE INDEX` statement is used to create indexes in tables.
Indexes are used to retrieve data from the database more quickly than otherwise. The users cannot see the indexes, they are just used to speed up searches/queries.
```sql
CREATE INDEX index_name
ON table_name (column1, column2, ...);
```
## Dates
**MySQL** comes with the following data types for storing a date or a date/time value in the database:
- `DATE` - format YYYY-MM-DD
- `DATETIME` - format: YYYY-MM-DD HH:MI:SS
- `TIMESTAMP` - format: YYYY-MM-DD HH:MI:SS
- `YEAR` - format YYYY or YY
## Data Types
### String
| Data type | Description |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CHAR(size) | A FIXED length string (can contain letters, numbers, and special characters). The _size_ parameter specifies the column length in characters - can be from 0 to 255. Default is 1 |
| VARCHAR(size) | A VARIABLE length string (can contain letters, numbers, and special characters). The _size_ parameter specifies the maximum string length in characters - can be from 0 to 65535 |
| BINARY(size) | Equal to CHAR(), but stores binary byte strings. The _size_ parameter specifies the column length in bytes. Default is 1 |
| VARBINARY(size) | Equal to VARCHAR(), but stores binary byte strings. The _size_ parameter specifies the maximum column length in bytes. |
| TINYBLOB | For BLOBs (Binary Large Objects). Max length: 255 bytes |
| TINYTEXT | Holds a string with a maximum length of 255 characters |
| TEXT(size) | Holds a string with a maximum length of 65,535 bytes |
| BLOB(size) | For BLOBs (Binary Large Objects). Holds up to 65,535 bytes of data |
| MEDIUMTEXT | Holds a string with a maximum length of 16,777,215 characters |
| MEDIUMBLOB | For BLOBs (Binary Large Objects). Holds up to 16,777,215 bytes of data |
| LONGTEXT | Holds a string with a maximum length of 4,294,967,295 characters |
| LONGBLOB | For BLOBs (Binary Large Objects). Holds up to 4,294,967,295 bytes of data |
| ENUM(val1, val2, val3, ...) | A string object that can have only one value, chosen from a list of possible values. You can list up to 65535 values in an ENUM list. If a value is inserted that is not in the list, a blank value will be inserted. The values are sorted in the order you enter them |
| SET(val1, val2, val3, ...) | A string object that can have 0 or more values, chosen from a list of possible values. You can list up to 64 values in a SET list |
### Numeric
| Data type | Description |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BIT(_size_) | A bit-value type. The number of bits per value is specified in _size_. The _size_ parameter can hold a value from 1 to 64. The default value for _size_ is 1. |
| TINYINT(_size_) | A very small integer. Signed range is from -128 to 127. Unsigned range is from 0 to 255. The _size_ parameter specifies the maximum display width (which is 255) |
| BOOL | Zero is considered as false, nonzero values are considered as true. |
| BOOLEAN | Equal to BOOL |
| SMALLINT(_size_) | A small integer. Signed range is from -32768 to 32767. Unsigned range is from 0 to 65535. The _size_ parameter specifies the maximum display width (which is 255) |
| MEDIUMINT(_size_) | A medium integer. Signed range is from -8388608 to 8388607. Unsigned range is from 0 to 16777215. The _size_ parameter specifies the maximum display width (which is 255) |
| INT(_size_) | A medium integer. Signed range is from -2147483648 to 2147483647. Unsigned range is from 0 to 4294967295. The _size_ parameter specifies the maximum display width (which is 255) |
| INTEGER(_size_) | Equal to INT(size) |
| BIGINT(_size_) | A large integer. Signed range is from -9223372036854775808 to 9223372036854775807. Unsigned range is from 0 to 18446744073709551615. The _size_ parameter specifies the maximum display width (which is 255) |
| FLOAT(_size_, _d_) | A floating point number. The total number of digits is specified in _size_. The number of digits after the decimal point is specified in the _d_ parameter. This syntax is deprecated in MySQL 8.0.17, and it will be removed in future MySQL versions |
| FLOAT(_p_) | A floating point number. MySQL uses the _p_ value to determine whether to use FLOAT or DOUBLE for the resulting data type. If _p_ is from 0 to 24, the data type becomes FLOAT(). If _p_ is from 25 to 53, the data type becomes DOUBLE() |
| DOUBLE(_size_, _d_) | A normal-size floating point number. The total number of digits is specified in _size_. The number of digits after the decimal point is specified in the _d_ parameter |
| DOUBLE PRECISION(_size_, _d_) | |
| DECIMAL(_size_, _d_) | An exact fixed-point number. The total number of digits is specified in _size_. The number of digits after the decimal point is specified in the _d_ parameter. The maximum number for _size_ is 65. The maximum number for _d_ is 30. The default value for _size_ is 10. The default value for _d_ is 0. |
| DEC(_size_, _d_) | Equal to DECIMAL(size,d) |
### Date & Time
| Data type | Description |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| DATE | A date. Format: YYYY-MM-DD. The supported range is from '1000-01-01' to '9999-12-31' |
| DATETIME(_fsp_) | A date and time combination. Format: YYYY-MM-DD hh:mm:ss. The supported range is from '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. Adding DEFAULT and ON UPDATE in the column definition to get automatic initialization and updating to the current date and time |
| TIMESTAMP(_fsp_) | A timestamp. TIMESTAMP values are stored as the number of seconds since the Unix epoch ('1970-01-01 00:00:00' UTC). Format: YYYY-MM-DD hh:mm:ss. The supported range is from '1970-01-01 00:00:01' UTC to '2038-01-09 03:14:07' UTC. Automatic initialization and updating to the current date and time can be specified using DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP in the column definition |
| TIME(_fsp_) | A time. Format: hh:mm:ss. The supported range is from '-838:59:59' to '838:59:59' |
| YEAR | A year in four-digit format. Values allowed in four-digit format: 1901 to 2155, and 0000. <br>MySQL 8.0 does not support year in two-digit format. |
# Functions
## String Functions
### CHARACTER_LENGTH()
The `CHARACTER_LENGTH()` function return the length of a string (in characters).
```sql
SELECT CHARACTER_LENGTH("SQL Tutorial") AS LengthOfString;
```
### CONCAT()
The `CONCAT()` function returns a concat string of parameters.
```sql
SELECT CONCAT(Name, LastName)
FROM persons;
```
### LOWER() & UPPER()
The `UPPER()` function converts a string to upper-case.
The `LOWER()` function converts a string to lower-case.
```sql
SELECT LOWER("SQL");
SELECT UPPER("SQL");
```
### TRIM() (RTRIM() & LTRIM())
The `TRIM()` function removes leading and trailing spaces from a string. `LTRIM()` & `RTRIM()` remove leading and trailing spaces from the left or right respectively.
```sql
SELECT TRIM('    SQL    ') AS TrimmedString;
```
### SUBSTRING()
The SUBSTRING() function extracts a substring from a string (starting at any position).
```sql
SUBSTRING(string, start, length)
```
### LPAD() & RPAD()
The `LPAD()` & `RPAD()` function left- or right-pads a string with another string, to a certain length.
```sql
RPAD(string, length, rpad_string)
```
### LEFT() & RIGHT()
These functions extract a number of characters from a string. (From left or right respectively)
```sql
RIGHT(string, number_of_chars)
```
### REVERSE()
The `REVERSE()` function reverses a string and returns the result.
### REPLACE()
The `REPLACE()` function replaces all occurrences of a substring within a string, with a new substring.
```sql
REPLACE(string, from_string, new_string)
```
### REPEAT()
The `REPEAT()` function repeats a string as many times as specified.
```sql
REPEAT(string, number)
```
## Numeric Functions
### MIN() & MAX()
The `MIN()` function returns the smallest value of the selected column.
The `MAX()` function returns the largest value of the selected column.
```sql
SELECT MIN(Price)
FROM Products;
SELECT MAX(Price)
FROM Products;
```
### COUNT()
The `COUNT()` function returns the number of rows that matches a specified criterion.
```sql
SELECT COUNT(*)
FROM Products;
```
### SUM()
The `SUM()` function returns the total sum of a numeric column.
Example:
```sql
SELECT SUM(Quantity) AS total
FROM OrderDetails;
```
Expressions:
```sql
SELECT SUM(Quantity * 10)
FROM OrderDetails;
```
### AVG()
The `AVG()` function returns the average value of a numeric column.
```sql
SELECT AVG(Price)
FROM Products;
SELECT * FROM Products
WHERE price > (SELECT AVG(price) FROM Products);
```
## Date Functions
### Extract information
1. **DAY()**: Returns the day of the month for a given date.
2. **HOUR()**: Returns the hour part for a given date.
3. **MINUTE()**: Returns the minute part of a time/datetime.
4. **SECOND()**: Returns the seconds part of a time/datetime.
5. **MICROSECOND()**: Returns the microsecond part of a time/datetime.
6. **DAYNAME()**: Returns the weekday name for a given date.
7. **MONTH()**: Returns the month for a given date
8. **MONTHNAME()**: Returns the name of the month for a given date.
8. **DAYOFMONTH()**: Returns the day of the month for a given date.
9. **DAYOFWEEK()**: Returns the weekday index for a given date.
10. **DAYOFYEAR()**: Returns the day of the year for a given date.
11. **QUARTER()**: Returns the quarter of the year for a given date value.
12. **WEEKDAY()**: Returns the weekday number for a given date.
13. **WEEKOFYEAR()**: Returns the week number for a given date.
### Create Datetimes
Current date and time:
```sql
NOW()
```

View file

@ -0,0 +1,34 @@
---
obj: meta
---
# Creational Patterns
- [Abstract Factory](creational/Abstract%20Factory%20Pattern.md)
- [Builder](creational/Builder%20Pattern.md)
- [Dependency Injection](creational/Dependency%20Injection%20Pattern.md)
- [Factory Method](creational/Factory%20Method%20Pattern.md)
- [Lazy Instantiation](creational/Lazy%20Instantiation%20Pattern.md)
- [Multiton](creational/Multiton%20Pattern.md)
- [Object Pool](creational/Object%20Pool%20Pattern.md)
- [Prototype](creational/Prototype%20Pattern.md)
- [RAII](creational/RAII%20Pattern.md)
- [Singleton](creational/Singleton%20Pattern.md)
# Structural Patterns
- [Adapter](structural/Adapter%20Pattern.md)
- [Bridge](structural/Bridge%20Patterns.md)
- [Composite](structural/Composite%20Pattern.md)
- [Decorator](structural/Decorator%20Pattern.md)
- [Facade](structural/Facade%20Pattern.md)
- [Flyweight](structural/Flyweight%20Pattern.md)
- [Proxy](structural/Proxy%20Pattern.md)
# Behavioral Patterns
- [Iterator](behavioral/Iterator%20Pattern.md)
- [Memento](behavioral/Memento%20Pattern.md)
- [Null Object](behavioral/Null%20Object%20Pattern.md)
- [Observer](behavioral/Observer%20Patterns.md)
- [State](behavioral/State%20Patterns.md)
- [Strategy](behavioral/Strategy%20Pattern.md)
- [Template Method](behavioral/Template%20Method%20Pattern.md)
- [Visitor](behavioral/Visitor%20Pattern.md)

View file

@ -0,0 +1,17 @@
---
obj: concept
---
# Iterator Pattern
## **Description:**
The Iterator Pattern is a behavioral design pattern that provides a way to access the elements of a collection sequentially without exposing its underlying representation. It defines a common interface for iterating over various types of collections, such as arrays, lists, trees, and more. The pattern separates the responsibility of iteration from the collection itself, promoting encapsulation and flexibility.
## **Example:**
[Rust](../../languages/Rust.md) has iterators which can be extended by functional programming methods like `map()`, etc.
```rust
trait Iterator<T> {
fn has_next(&self) -> bool;
fn next(&mut self) -> Option<T>;
}
```

View file

@ -0,0 +1,93 @@
---
obj: concept
---
# Memento Pattern
## **Description:**
The Memento Pattern is a behavioral design pattern that allows you to capture and externalize an object's internal state so that the object can be restored to that state later. It is often used to implement undo functionality, snapshots, or checkpoints in an application without exposing the object's internal structure.
**How it's Used:**
1. **Originator**: Define an originator class (or object) that has an internal state that needs to be saved and restored.
2. **Memento**: Create a memento class that represents the state of the originator object. This class should provide methods to get and set the originator's state.
3. **Caretaker**: Implement a caretaker class that is responsible for keeping track of and managing the memento objects. The caretaker should have a collection to store multiple mementos if needed.
4. **Save and Restore**: The originator can create memento objects to save its state, and the caretaker can store these mementos. When needed, the originator can restore its state from a memento provided by the caretaker.
## **Example:**
Let's create an example of the Memento Pattern in [Rust](../../languages/Rust.md) to implement a simple text editor with undo functionality.
```rust
// Originator: TextEditor
struct TextEditor {
text: String,
}
impl TextEditor {
fn new() -> Self {
TextEditor { text: String::new() }
}
fn set_text(&mut self, text: String) {
self.text = text;
}
fn get_text(&self) -> String {
self.text.clone()
}
fn create_memento(&self) -> EditorMemento {
EditorMemento::new(self.text.clone())
}
fn restore_from_memento(&mut self, memento: EditorMemento) {
self.text = memento.get_saved_text();
}
}
// Memento: EditorMemento
struct EditorMemento {
saved_text: String,
}
impl EditorMemento {
fn new(text: String) -> Self {
EditorMemento { saved_text: text }
}
fn get_saved_text(&self) -> String {
self.saved_text.clone()
}
}
// Caretaker: EditorHistory
struct EditorHistory {
mementos: Vec<EditorMemento>,
}
impl EditorHistory {
fn new() -> Self {
EditorHistory { mementos: Vec::new() }
}
fn add_memento(&mut self, memento: EditorMemento) {
self.mementos.push(memento);
}
fn get_memento(&self, index: usize) -> Option<&EditorMemento> {
self.mementos.get(index)
}
}
fn main() {
let mut editor = TextEditor::new();
let mut history = EditorHistory::new();
editor.set_text(String::from("First version"));
history.add_memento(editor.create_memento());
editor.set_text(String::from("Second version"));
history.add_memento(editor.create_memento());
editor.restore_from_memento(history.get_memento(0).unwrap().clone());
println!("Restored version: {}", editor.get_text());
}
```

View file

@ -0,0 +1,53 @@
---
obj: concept
---
# Null Object Pattern
## **Description:**
The Null Object Pattern is a behavioral design pattern that provides an object as a surrogate for the lack of an object of a given type. It allows you to handle the absence of an object gracefully without explicit null checks, improving code readability and robustness. The null object typically provides default behavior or no-op implementations for the methods of the original object.
**How it's Used:**
1. **Interface or Abstract Class**: Define an interface or abstract class that represents the common behavior of the objects in question.
2. **Concrete Implementations**: Create concrete implementations of the interface or abstract class for real objects that provide meaningful functionality.
3. **Null Object**: Create a special null object class that also implements the interface or extends the abstract class. This null object should provide default or no-op implementations for the methods.
4. **Client Code**: In client code, use the null object when you expect an object of the interface type but want to gracefully handle the case when no real object is available.
## **Example:**
Let's create an example of the Null Object Pattern in [Python](../../languages/Python.md) for handling logging. We'll define an interface for a logger, create real logger and null logger implementations, and demonstrate their use.
```python
from abc import ABC, abstractmethod
# Step 1: Define an interface for the logger
class Logger(ABC):
@abstractmethod
def log(self, message):
pass
# Step 2: Create a real logger implementation
class ConsoleLogger(Logger):
def log(self, message):
print(f"Console Log: {message}")
# Step 3: Create a null logger implementation
class NullLogger(Logger):
def log(self, message):
pass
# Step 4: Client code
def main():
# Real logger
logger = ConsoleLogger()
logger.log("This is a real log message.")
# Null logger
null_logger = NullLogger()
null_logger.log("This will not be logged.")
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `Logger` interface (Step 1) and create a real logger implementation (`ConsoleLogger`) that prints log messages to the console (Step 2). We also create a null logger implementation (`NullLogger`) that does nothing when `log` is called (Step 3).
In the `main` function (Step 4), we demonstrate using both the real logger and the null logger. When you use the null logger, you can safely handle the case where logging is not required without explicit null checks. This pattern is particularly useful when you want to avoid conditional statements throughout your code for handling null cases.

View file

@ -0,0 +1,89 @@
---
obj: concept
---
# Observer Pattern
## **Description:**
The Observer Pattern is a behavioral design pattern that defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. It's used to establish dynamic, distributed, and loosely coupled communication between objects, making it easy to maintain consistency and synchronization.
**How it's Used:**
1. **Subject Interface**: Define a subject interface or abstract class that declares methods for attaching, detaching, and notifying observers. It should also have a method to update its state.
2. **Concrete Subject**: Create a concrete subject class that implements the subject interface. This class maintains a list of its observers and notifies them when its state changes.
3. **Observer Interface**: Define an observer interface with an update method that subjects will call to notify observers of changes.
4. **Concrete Observer**: Create concrete observer classes that implement the observer interface. These classes define how they respond to updates from the subject.
5. **Client Code**: In client code, create instances of concrete subjects and observers, attach observers to subjects, and let the system handle the rest of the communication.
**Example:** Let's create an example of the Observer Pattern in [Python](../../languages/Python.md) to model a simple weather monitoring system where weather stations act as subjects and display panels act as observers.
```python
from abc import ABC, abstractmethod
# Step 1: Subject Interface
class Subject(ABC):
@abstractmethod
def attach(self, observer):
pass
@abstractmethod
def detach(self, observer):
pass
@abstractmethod
def notify(self):
pass
# Step 2: Concrete Subject (WeatherStation)
class WeatherStation(Subject):
def __init__(self):
self.observers = []
self.temperature = 0.0
def attach(self, observer):
self.observers.append(observer)
def detach(self, observer):
self.observers.remove(observer)
def notify(self):
for observer in self.observers:
observer.update(self.temperature)
def set_temperature(self, temperature):
self.temperature = temperature
self.notify()
# Step 3: Observer Interface
class Observer(ABC):
@abstractmethod
def update(self, temperature):
pass
# Step 4: Concrete Observer (DisplayPanel)
class DisplayPanel(Observer):
def __init__(self, name):
self.name = name
def update(self, temperature):
print(f"{self.name} Display: Temperature is {temperature}°C")
# Step 5: Client Code
def main():
weather_station = WeatherStation()
panel1 = DisplayPanel("Panel 1")
panel2 = DisplayPanel("Panel 2")
weather_station.attach(panel1)
weather_station.attach(panel2)
weather_station.set_temperature(25.5)
weather_station.set_temperature(30.0)
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `Subject` interface (Step 1) with `attach`, `detach`, and `notify` methods. The `WeatherStation` class (Step 2) implements the subject interface, maintains a list of observers, and notifies them when the temperature changes.
We also define an `Observer` interface (Step 3) with an `update` method. The `DisplayPanel` class (Step 4) implements the observer interface and defines how it responds to updates.
In the `main` function (Step 5), we create a weather station and two display panels. We attach the display panels to the weather station, and when the weather station's temperature changes, it automatically notifies the attached display panels to update their displays. This allows for real-time synchronization between the weather station and the display panels.

View file

@ -0,0 +1,82 @@
---
obj: concept
---
# State Pattern
## **Description:**
The State Pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. The object appears to change its class, making it useful for modeling objects with complex state-dependent behaviors. It encapsulates the states as separate classes and allows the context (the object whose state is changing) to delegate state-specific behavior to these state classes.
**How it's Used:**
1. **State Interface/Abstract Class**: Define a state interface or abstract class that declares methods for the various actions or behaviors that can change based on the state.
2. **Concrete States**: Create concrete state classes that implement the state interface/abstract class. Each concrete state class represents a specific state and provides its own implementation of the state-specific behaviors.
3. **Context**: Define a context class that maintains a reference to the current state object. The context class delegates state-specific behavior to the current state object.
4. **State Transition**: Implement methods in the context class for transitioning between states. These methods change the current state to a different state as needed.
## **Example:**
Let's create an example of the State Pattern in [Python](../../languages/Python.md) to model the behavior of a traffic light with three states: "Green," "Yellow," and "Red."
```python
from abc import ABC, abstractmethod
# Step 1: State Interface
class TrafficLightState(ABC):
@abstractmethod
def display(self):
pass
@abstractmethod
def transition(self, traffic_light):
pass
# Step 2: Concrete States
class GreenLightState(TrafficLightState):
def display(self):
return "Green"
def transition(self, traffic_light):
traffic_light.set_state(YellowLightState())
class YellowLightState(TrafficLightState):
def display(self):
return "Yellow"
def transition(self, traffic_light):
traffic_light.set_state(RedLightState())
class RedLightState(TrafficLightState):
def display(self):
return "Red"
def transition(self, traffic_light):
traffic_light.set_state(GreenLightState())
# Step 3: Context (TrafficLight)
class TrafficLight:
def __init__(self):
self.state = GreenLightState()
def set_state(self, state):
self.state = state
def change_state(self):
self.state.transition(self)
def display_state(self):
return self.state.display()
# Step 4: Client Code
def main():
traffic_light = TrafficLight()
for _ in range(5):
print(f"Current Light: {traffic_light.display_state()}")
traffic_light.change_state()
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `TrafficLightState` interface (Step 1) with `display` and `transition` methods. We create three concrete state classes (`GreenLightState`, `YellowLightState`, and `RedLightState`) (Step 2) that implement this interface, representing the states of the traffic light.
The `TrafficLight` class (Step 3) is the context class that maintains a reference to the current state and delegates state-specific behavior to that state. The `change_state` method transitions to the next state in the sequence.
In the `main` function (Step 4), we create a traffic light, display its state, and change the state to simulate the behavior of a traffic light changing from green to yellow to red and back to green. The State Pattern allows us to manage the traffic light's behavior in a flexible and maintainable way.

View file

@ -0,0 +1,73 @@
---
obj: concept
---
# Strategy Pattern
## **Description:**
The Strategy Pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one of them, and makes them interchangeable. It allows clients to choose an appropriate algorithm from a family of algorithms at runtime, without altering the code that uses the algorithm. This pattern promotes flexibility, extensibility, and the ability to switch between different algorithms or strategies.
**How it's Used:**
1. **Strategy Interface/Abstract Class**: Define a strategy interface or abstract class that declares a method or a set of methods for the algorithms to be encapsulated.
2. **Concrete Strategies**: Create concrete strategy classes that implement the strategy interface/abstract class. Each concrete strategy represents a specific algorithm.
3. **Context**: Define a context class that contains a reference to a strategy object and can switch between different strategies. The context class uses the strategy object to perform its operations.
4. **Client Code**: Clients create instances of the context class and configure them with the desired strategy. Clients can change the strategy at runtime, and the context will use the currently configured strategy to perform its tasks.
## **Example:**
Let's create an example of the Strategy Pattern in [Python](../../languages/Python.md) to model a payment system where customers can choose different payment methods.
```python
from abc import ABC, abstractmethod
# Step 1: Strategy Interface
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
# Step 2: Concrete Strategies
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using Credit Card.")
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using PayPal.")
class BankTransferPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using Bank Transfer.")
# Step 3: Context (PaymentContext)
class PaymentContext:
def __init__(self, strategy):
self.strategy = strategy
def set_payment_strategy(self, strategy):
self.strategy = strategy
def perform_payment(self, amount):
self.strategy.pay(amount)
# Step 4: Client Code
def main():
credit_card_strategy = CreditCardPayment()
paypal_strategy = PayPalPayment()
bank_transfer_strategy = BankTransferPayment()
context = PaymentContext(credit_card_strategy)
context.perform_payment(100.0)
# Change payment strategy at runtime
context.set_payment_strategy(paypal_strategy)
context.perform_payment(50.0)
context.set_payment_strategy(bank_transfer_strategy)
context.perform_payment(75.0)
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `PaymentStrategy` interface (Step 1) with a `pay` method. We create three concrete strategy classes (`CreditCardPayment`, `PayPalPayment`, and `BankTransferPayment`) (Step 2) that implement this interface, representing different payment methods.
The `PaymentContext` class (Step 3) is the context class that contains a reference to a strategy object and uses it to perform payments. Clients (Step 4) create instances of the context class and configure them with the desired payment strategy. Clients can change the strategy at runtime, and the context will use the currently configured strategy to perform payments. This allows for easy swapping of payment methods without changing the client code.

View file

@ -0,0 +1,75 @@
---
obj: concept
---
# Template Method Pattern
## **Description:**
The Template Method Pattern is a behavioral design pattern that defines the skeleton of an algorithm in the base class but allows subclasses to override specific steps of the algorithm without changing its structure. It provides a way to define the overall algorithm's structure while allowing customization of certain steps by subclasses. This pattern promotes code reuse and follows the "Don't Call Us, We'll Call You" principle, where the base class controls the flow of the algorithm.
**How it's Used:**
1. **Abstract Template Class**: Create an abstract base class (or interface) that defines the template method, which is the skeleton of the algorithm. The template method consists of a series of steps, some of which may be abstract or have default implementations.
2. **Concrete Subclasses**: Create concrete subclasses that inherit from the abstract template class. These subclasses provide concrete implementations for the abstract steps of the template method.
3. **Template Method**: The template method in the abstract base class controls the overall algorithm's flow by calling the individual steps. It should be marked as final or not overridable to prevent subclasses from altering the algorithm's structure.
## **Example:**
Let's create an example of the Template Method Pattern in [Python](../../languages/Python.md) for a beverage preparation process with a template method for brewing beverages.
```python
from abc import ABC, abstractmethod
# Step 1: Abstract Template Class
class Beverage(ABC):
def prepare(self):
self.boil_water()
self.brew()
self.pour_in_cup()
self.add_condiments()
@abstractmethod
def brew(self):
pass
@abstractmethod
def add_condiments(self):
pass
def boil_water(self):
print("Boiling water")
def pour_in_cup(self):
print("Pouring into cup")
# Step 2: Concrete Subclasses
class Tea(Beverage):
def brew(self):
print("Steeping the tea")
def add_condiments(self):
print("Adding lemon")
class Coffee(Beverage):
def brew(self):
print("Dripping coffee through filter")
def add_condiments(self):
print("Adding sugar and milk")
# Step 3: Client Code
def main():
tea = Tea()
coffee = Coffee()
print("Making tea:")
tea.prepare()
print("\nMaking coffee:")
coffee.prepare()
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `Beverage` abstract base class (Step 1) with a `prepare` method that represents the template method. The `prepare` method calls four steps: `boil_water`, `brew`, `pour_in_cup`, and `add_condiments`. The `brew` and `add_condiments` methods are declared as abstract, allowing concrete subclasses (e.g., `Tea` and `Coffee`) to provide their implementations for these steps.
Concrete subclasses (Step 2) such as `Tea` and `Coffee` inherit from the `Beverage` class and provide their implementations for the `brew` and `add_condiments` steps.
In the `main` function (Step 3), we create instances of `Tea` and `Coffee` and invoke the `prepare` method on each, which follows the template method's algorithm for preparing beverages. Subclasses customize the steps to produce specific types of beverages while reusing the common template method structure.

View file

@ -0,0 +1,96 @@
---
obj: concept
---
# Visitor Pattern
## **Description:**
The Visitor Pattern is a behavioral design pattern that allows you to add new operations to a set of related classes without modifying their code. It separates the algorithm (or operation) from the object structure, enabling you to define new behaviors (visitors) independently and apply them to existing objects. This pattern is useful when you have a stable set of classes but need to frequently introduce new operations on those classes.
**How it's Used:**
1. **Element Interface**: Define an element interface that declares an `accept` method which accepts a visitor.
2. **Concrete Elements**: Create concrete element classes that implement the element interface. These are the objects that will be visited by visitors.
3. **Visitor Interface**: Define a visitor interface that declares visit methods for each concrete element type. The visitor interface should have one visit method for each type of element it can visit.
4. **Concrete Visitors**: Create concrete visitor classes that implement the visitor interface. Each concrete visitor provides implementations for the visit methods to perform specific operations on the elements.
5. **Element Structure**: Create a structure (e.g., a collection) of concrete elements that need to be visited.
6. **Accept Visitor**: In the concrete elements, implement the `accept` method to call the appropriate visit method on the visitor.
7. **Client Code**: In client code, create instances of concrete elements and visitors, and apply visitors to elements as needed.
## **Example:**
Let's create an example of the Visitor Pattern in [Python](../../languages/Python.md) to model a document structure with elements (e.g., paragraphs and tables) and a visitor that counts the elements.
```python
from abc import ABC, abstractmethod
# Step 1: Element Interface
class Element(ABC):
@abstractmethod
def accept(self, visitor):
pass
# Step 2: Concrete Elements
class Paragraph(Element):
def accept(self, visitor):
visitor.visit_paragraph(self)
class Table(Element):
def accept(self, visitor):
visitor.visit_table(self)
# Step 3: Visitor Interface
class Visitor(ABC):
@abstractmethod
def visit_paragraph(self, paragraph):
pass
@abstractmethod
def visit_table(self, table):
pass
# Step 4: Concrete Visitors
class ElementCounter(Visitor):
def __init__(self):
self.paragraph_count = 0
self.table_count = 0
def visit_paragraph(self, paragraph):
self.paragraph_count += 1
def visit_table(self, table):
self.table_count += 1
# Step 5: Element Structure
class Document:
def __init__(self, elements):
self.elements = elements
def accept(self, visitor):
for element in self.elements:
element.accept(visitor)
# Step 7: Client Code
def main():
paragraph1 = Paragraph()
paragraph2 = Paragraph()
table1 = Table()
table2 = Table()
elements = [paragraph1, table1, paragraph2, table2]
document = Document(elements)
counter = ElementCounter()
document.accept(counter)
print(f"Paragraph Count: {counter.paragraph_count}")
print(f"Table Count: {counter.table_count}")
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define an `Element` interface (Step 1) with an `accept` method. We create two concrete element classes (`Paragraph` and `Table`) that implement this interface (Step 2).
We define a `Visitor` interface (Step 3) with `visit_paragraph` and `visit_table` methods. We then create a concrete visitor class (`ElementCounter`) that implements the visitor interface (Step 4) and counts the elements it visits.
The `Document` class (Step 5) contains a collection of elements, and it implements the `accept` method to iterate through the elements and call their `accept` method to let the visitor visit them.
In the `main` function (Step 7), we create instances of elements and visitors, apply the visitor to the document, and display the counts of paragraphs and tables visited. This separation allows us to add new visitors to perform different operations on the document structure without modifying the element classes.

View file

@ -0,0 +1,41 @@
---
obj: concept
---
# Abstract Factory Pattern
## **Description:**
The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. It is often used to ensure that a system is compatible with multiple families of objects, allowing you to switch between these families without changing the client code.
**How it's Used:**
1. **Abstract Factory Interface**: Define an abstract factory interface that declares a set of creation methods for creating abstract product objects. Each method corresponds to a different type of product.
2. **Concrete Factories**: Create concrete factory classes that implement the abstract factory interface. Each concrete factory is responsible for creating a specific family of related products.
3. **Abstract Product Interface**: Define an abstract product interface that declares the common methods that concrete product classes must implement. Each product family will have its own set of product interfaces.
4. **Concrete Products**: Create concrete product classes that implement the abstract product interfaces. These classes provide specific implementations for the products within each family.
5. **Client Code**: In the client code, use the abstract factory to create families of objects. Clients interact with the abstract factory and abstract product interfaces rather than directly with concrete classes.
## **Example:**
Let's say you're building a user interface (UI) framework that can be used on both desktop and mobile platforms. You want to ensure that UI components like buttons and text fields are consistent within each platform but can be easily switched between platforms. Here's how the Abstract Factory Pattern can be applied:
- **Abstract Factory Interface**: Define an `AbstractUIFactory` interface with methods like `createButton` and `createTextField`.
- **Concrete Factories**: Create two concrete factory classes: `DesktopUIFactory` and `MobileUIFactory`, both implementing the `AbstractUIFactory`. The `DesktopUIFactory` creates desktop-style UI components, while the `MobileUIFactory` creates mobile-style UI components.
- **Abstract Product Interfaces**: Define abstract product interfaces like `Button` and `TextField` that specify the methods these UI components should have.
- **Concrete Products**: Create concrete product classes like `DesktopButton`, `MobileButton`, `DesktopTextField`, and `MobileTextField`, each implementing the corresponding abstract product interfaces.
- **Client Code**: In your application, use the appropriate factory (either `DesktopUIFactory` or `MobileUIFactory`) to create UI components. For example:
```java
AbstractUIFactory factory = getUIFactoryForPlatform();
Button button = factory.createButton();
TextField textField = factory.createTextField();
```
By using the Abstract Factory Pattern, you can switch between desktop and mobile UI components seamlessly by changing the factory you use, without modifying the client code.

View file

@ -0,0 +1,27 @@
---
obj: concept
---
# Builder Pattern
## **Description:**
The Builder Pattern is a creational design pattern used to construct a complex object step by step. It separates the construction of an object from its representation, allowing you to create different variations of the same object with a clear and consistent API. This pattern is particularly useful when an object has many optional components or configuration settings.
**How it's Used:**
1. **Builder Interface**: Define an abstract builder interface that declares methods for constructing different parts of the complex object. These methods should cover all possible configurations.
2. **Concrete Builders**: Create concrete builder classes that implement the builder interface. Each concrete builder is responsible for building a specific variant of the complex object.
3. **Product**: Define the complex object (the product) that you want to create. This object should have a way to accept values or components set by the builder.
4. **Director (Optional)**: You can create a director class (optional) that orchestrates the construction process using a specific builder. The director simplifies client code by providing a higher-level interface to construct the object.
5. **Client Code**: In your application, use the builder to construct the complex object step by step. You can chain method calls together for a more fluent and readable construction process.
## **Example:**
Consider building a `Computer` object with various optional components such as a processor, memory, storage, and graphics card. Here's how the Builder Pattern can be applied:
- **Builder Interface**: Define an `ComputerBuilder` interface with methods like `setProcessor`, `setMemory`, `setStorage`, and `setGraphicsCard`.
- **Concrete Builders**: Create concrete builder classes like `GamingComputerBuilder` and `OfficeComputerBuilder`, both implementing the `ComputerBuilder` interface. Each builder knows how to construct a specific type of computer.
- **Product**: Define the `Computer` class with fields for processor, memory, storage, and graphics card, and a constructor to initialize these fields.
- **Director (Optional)**: Create a `ComputerDirector` class that takes a `ComputerBuilder` as a parameter. The director can provide higher-level methods like `buildGamingComputer` or `buildOfficeComputer`.
- **Client Code**: In your application, use the builder to construct a computer with the desired components:
```java
ComputerBuilder builder = new GamingComputerBuilder();
Computer gamingComputer = builder.setMemory(16).buildComputer();
```

View file

@ -0,0 +1,46 @@
---
obj: concept
---
# Dependency Injection
## **Description:**
Dependency Injection (DI) is a design pattern used in software development to achieve Inversion of Control (IoC). It helps manage the dependencies between components or classes by externalizing the dependencies and injecting them rather than having the components create their own dependencies. This promotes loose coupling, testability, and flexibility in your code.
**How it's Used:**
1. **Dependency**: Identify the dependencies that a class or component needs to function properly. These dependencies can be other objects, services, or configurations.
2. **Injection Mechanism**: Create a mechanism to provide these dependencies to the class that needs them. This can be done in several ways, such as constructor injection, setter injection, or method injection.
3. **Injection Container (Optional)**: In larger applications, you may use an injection container or a framework (e.g., Spring, Guice) to manage and automatically inject dependencies. These containers can handle the creation and wiring of objects.
4. **Client Code**: In your application, create instances of the classes and inject the required dependencies. This can be done manually or by using an injection container.
## **Example:**
Consider a simple Java application where you have a `UserService` class that depends on a `UserRepository` to retrieve user data from a database. Here's how Dependency Injection can be applied:
- **Identify Dependencies**: Recognize that `UserService` depends on `UserRepository`.
- **Injection Mechanism**: Use constructor injection to inject the `UserRepository` dependency into the `UserService` class.
```java
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// Use userRepository to perform user-related operations
}
```
- **Client Code**: In your application code, create instances of `UserRepository` and `UserService`, and inject the `UserRepository` into the `UserService`.
```java
public class Main {
public static void main(String[] args) {
UserRepository userRepository = new UserRepository(); // or use an injection container
UserService userService = new UserService(userRepository);
// Use the userService to work with users
}
}
```
By using Dependency Injection, you've decoupled the `UserService` and `UserRepository`, making it easier to replace or test these components independently. You can change the `UserRepository` implementation or switch to a mock repository for testing without modifying the `UserService` class. This promotes modularity and maintainability in your code.

View file

@ -0,0 +1,87 @@
---
obj: concept
---
# Factory Method Pattern
## **Description:**
The Factory Method Pattern is a creational design pattern that defines an interface for creating objects but allows subclasses to alter the type of objects that will be created. It provides a way to delegate the responsibility of instantiating objects to subclasses, promoting flexibility and extensibility in your code.
**How it's Used:**
1. **Creator Interface or Abstract Class**: Define an abstract class or interface, often referred to as the "creator," that declares a method for creating objects. This method is the factory method.
2. **Concrete Creators**: Create concrete subclasses of the creator class, each of which implements the factory method. These subclasses decide which class of objects to create and return.
3. **Product**: Define an abstract product class or interface that represents the type of object created by the factory method.
4. **Concrete Products**: Create concrete classes that implement the product interface. Each concrete product represents a specific variant or type of object.
5. **Client Code**: In your application, use the creator class and its factory method to create objects. The client code typically works with the creator interface or abstract class rather than concrete classes.
## **Example:**
Imagine you are developing a document processing application that can handle different types of documents, such as `TextDocument` and `SpreadsheetDocument`. Here's how the Factory Method Pattern can be applied:
- **Creator Interface or Abstract Class**: Define an abstract class called `DocumentCreator` with a factory method named `createDocument`.
```java
public abstract class DocumentCreator {
public abstract Document createDocument();
}
```
- **Concrete Creators**: Create concrete subclasses of `DocumentCreator`, such as `TextDocumentCreator` and `SpreadsheetDocumentCreator`. Each subclass implements the `createDocument` method to return a specific type of document
```java
public class TextDocumentCreator extends DocumentCreator {
@Override
public Document createDocument() {
return new TextDocument();
}
}
public class SpreadsheetDocumentCreator extends DocumentCreator {
@Override
public Document createDocument() {
return new SpreadsheetDocument();
}
}
```
- **Product**: Define an abstract `Document` class or interface that represents the common operations for documents.
```java
public abstract class Document {
public abstract void open();
public abstract void save();
}
```
- **Concrete Products**: Create concrete classes like `TextDocument` and `SpreadsheetDocument` that implement the `Document` interface with specific implementations.
```java
public class TextDocument extends Document {
@Override
public void open() {
System.out.println("Opening Text Document");
}
@Override
public void save() {
System.out.println("Saving Text Document");
}
}
public class SpreadsheetDocument extends Document {
@Override
public void open() {
System.out.println("Opening Spreadsheet Document");
}
@Override
public void save() {
System.out.println("Saving Spreadsheet Document");
}
}
```
- **Client Code**: In your application, use the creator classes and their factory methods to create documents without knowing the concrete document classes:
```java
DocumentCreator textDocumentCreator = new TextDocumentCreator();
Document textDocument = textDocumentCreator.createDocument();
textDocument.open();
textDocument.save();
DocumentCreator spreadsheetDocumentCreator = new SpreadsheetDocumentCreator();
Document spreadsheetDocument = spreadsheetDocumentCreator.createDocument();
spreadsheetDocument.open();
spreadsheetDocument.save();
```
The Factory Method Pattern allows you to extend your application with new document types by creating additional concrete creators and products without modifying existing client code, promoting code reuse and maintainability.

View file

@ -0,0 +1,51 @@
---
obj: concept
---
# Lazy Instantiation
## **Description:**
Lazy Instantiation is a design pattern that defers the creation of an object until it is actually needed. This pattern is particularly useful when creating or initializing an object is expensive in terms of time or resources, and you want to postpone it until the last possible moment to improve performance or save resources.
**How it's Used:**
1. **Identify Expensive Objects**: Determine which objects or resources in your application are expensive to create or initialize.
2. **Initialization on First Use**: Instead of creating these objects when the application starts, initialize them only when they are first requested by a client or when they are needed for a specific task.
3. **Lazy Initialization Mechanism**: Implement a mechanism to perform lazy initialization. Common techniques include using a null check, a flag, or a synchronized block to ensure that the object is created only once and when it's required.
4. **Client Code**: In your application, access or request the object as needed. The lazy initialization mechanism will ensure that the object is created the first time it's requested and reused for subsequent requests.
## **Example:**
Consider an application that manages a large collection of images, and loading each image into memory is resource-intensive. To save resources and improve performance, you can implement Lazy Instantiation for image loading:
- **Identify Expensive Objects**: Recognize that loading images into memory is resource-intensive.
- **Lazy Initialization Mechanism**: Create a class called `ImageLoader` that manages the loading of images. In this class, implement a lazy initialization mechanism for loading images on-demand.
```java
public class ImageLoader {
private Map<String, Image> loadedImages = new HashMap<>();
public Image getImage(String filename) {
if (!loadedImages.containsKey(filename)) {
// Load the image from disk or a remote source
Image image = loadImageFromFile(filename);
loadedImages.put(filename, image);
}
return loadedImages.get(filename);
}
private Image loadImageFromFile(String filename) {
// Code to load the image from disk or a remote source
// ...
return new Image(filename);
}
}
```
- **Client Code**: In your application, when you need to display an image, use the `ImageLoader` to obtain the image. The `ImageLoader` will load the image from the source only when requested and cache it for future use:
```java
ImageLoader imageLoader = new ImageLoader();
Image image1 = imageLoader.getImage("image1.jpg"); // Loaded when first requested
Image image2 = imageLoader.getImage("image2.jpg"); // Loaded when first requested
// Later in the application
Image image3 = imageLoader.getImage("image1.jpg"); // Reused from cache
```
By applying Lazy Instantiation in this example, you ensure that images are loaded into memory only when needed, conserving resources and improving the application's responsiveness. The images are cached for reuse, further enhancing performance when the same image is requested multiple times.

View file

@ -0,0 +1,54 @@
---
obj: concept
---
# Multiton Pattern
## **Description:**
The Multiton Pattern is a variation of the [Singleton Pattern](Singleton%20Pattern.md) that ensures a class has only a limited number of instances, where each instance is uniquely identified by a key. Unlike the [Singleton Pattern](Singleton%20Pattern.md), which allows only one instance of a class, the Multiton Pattern allows multiple instances, each associated with a specific key.
**How it's Used:**
1. **Multiton Class**: Define a class that you want to limit the number of instances for. This class will manage multiple instances, each associated with a unique key.
2. **Private Constructor**: Ensure that the constructor of the class is private to prevent external instantiation.
3. **Internal Registry**: Create an internal registry (usually a dictionary or map) within the class to store instances associated with their respective keys.
4. **Factory Method**: Implement a factory method or a static method within the class to create or retrieve instances based on keys.
5. **Use Keys**: When you need an instance of the class, provide a key to the factory method. The method will either create a new instance or return an existing instance associated with the provided key.
## **Example:**
Let's say you're creating a logging system for your application, and you want to have separate loggers for different modules. You can use the Multiton Pattern to ensure that each module has its own logger:
- **Multiton Class**: Define a `Logger` class.
```java
public class Logger {
private static final Map<String, Logger> instances = new HashMap<>();
private Logger() {
// Private constructor
}
public static Logger getInstance(String module) {
if (!instances.containsKey(module)) {
instances.put(module, new Logger());
}
return instances.get(module);
}
public void log(String message) {
// Logging implementation
System.out.println(message);
}
}
```
- **Private Constructor**: Ensure that the constructor of the `Logger` class is private to prevent external instantiation.
- **Internal Registry**: Use a `Map<String, Logger>` (`instances`) to store logger instances associated with their respective modules (keys).
- **Factory Method**: Implement a `getInstance` static method that takes a `module` parameter and returns a `Logger` instance associated with that module. If an instance for the module does not exist, create one and store it in the registry.
- **Use Keys**: In your application, when you need a logger for a specific module, use the `Logger.getInstance(module)` method to obtain or create the logger instance.
```java
Logger loggerA = Logger.getInstance("ModuleA");
Logger loggerB = Logger.getInstance("ModuleB");
loggerA.log("Log message for ModuleA");
loggerB.log("Log message for ModuleB");
```
By using the Multiton Pattern, you ensure that each module gets its own unique logger instance, identified by the module name. This allows you to have separate loggers for different parts of your application while keeping the logging code centralized and manageable.

View file

@ -0,0 +1,87 @@
---
obj: concept
---
# Object Pool Pattern
## **Description:**
The Object Pool Pattern is a creational design pattern that manages a pool of reusable objects to avoid the overhead of creating and destroying objects frequently. It provides a way to efficiently manage and reuse a limited number of instances of a class, especially when creating and initializing these instances is resource-intensive.
**How it's Used:**
1. **Create a Pool**: Create a pool of objects that you want to reuse. These objects could be expensive to create, initialize, or destroy.
2. **Initialization**: Initialize the pool by creating a predefined number of objects and adding them to the pool.
3. **Object Request**: When an object is needed, instead of creating a new one, request an object from the pool.
4. **Object Return**: After using an object, return it to the pool for reuse. This is typically done by marking the object as available.
5. **Manage Pool Size (Optional)**: Implement a mechanism to ensure that the pool doesn't exceed a maximum size. If the pool is empty and an object is requested, you can decide whether to create a new object or wait until an object becomes available.
## **Example:**
Consider a scenario where you have a web server that handles incoming HTTP requests. Creating a new connection to a database for each request can be expensive. You can use the Object Pool Pattern to manage a pool of database connections efficiently:
- **Create a Pool**: Define a `DatabaseConnection` class to represent database connections.
- **Initialization**: Create and initialize a fixed number of database connections when the application starts. Add these connections to the pool.
- **Object Request**: When a new HTTP request arrives and requires a database connection, request a connection from the pool.
- **Object Return**: After handling the request, return the database connection to the pool for reuse.
- **Manage Pool Size (Optional)**: Implement mechanisms to control the pool size, such as setting a maximum number of connections or waiting for a connection to become available if the pool is empty.
Here's a simplified example in Java:
```java
public class DatabaseConnection {
private boolean inUse;
public DatabaseConnection() {
// Initialize the database connection
// ...
}
public void markInUse() {
inUse = true;
}
public void markAvailable() {
inUse = false;
}
public boolean isInUse() {
return inUse;
}
}
public class ConnectionPool {
private List<DatabaseConnection> connections;
public ConnectionPool(int poolSize) {
connections = new ArrayList<>();
for (int i = 0; i < poolSize; i++) {
connections.add(new DatabaseConnection());
}
}
public synchronized DatabaseConnection getConnection() {
for (DatabaseConnection connection : connections) {
if (!connection.isInUse()) {
connection.markInUse();
return connection;
}
}
return null; // or create a new connection if allowed
}
public synchronized void releaseConnection(DatabaseConnection connection) {
connection.markAvailable();
}
}
// In your web server code
ConnectionPool pool = new ConnectionPool(10); // Initialize a pool with 10 database connections
// When handling an HTTP request
DatabaseConnection connection = pool.getConnection();
if (connection != null) {
// Use the connection for database operations
// ...
// Return the connection to the pool when done
pool.releaseConnection(connection);
}
```
By using the Object Pool Pattern, you can efficiently manage and reuse database connections, reducing the overhead of creating and destroying connections for each HTTP request. This can improve the performance and resource usage of your web server.

View file

@ -0,0 +1,79 @@
---
obj: concept
---
# Prototype Pattern
## **Description:**
The Prototype Pattern is a creational design pattern that allows you to create new objects by copying an existing object, known as the "prototype." It is particularly useful when the cost of creating an object is more expensive or complex than copying it, or when you want to create new objects with the same initial state as an existing one.
**How it's Used:**
1. **Prototype Interface or Abstract Class**: Define a common interface or abstract class for all concrete prototypes. This interface should include a method for cloning the object.
2. **Concrete Prototypes**: Create concrete classes that implement the prototype interface or extend the prototype abstract class. These classes define the specific properties and behaviors of the objects you want to clone.
3. **Clone Method**: Implement the clone method in each concrete prototype class. This method should create a new instance of the same class and copy the state from the current instance to the new one.
4. **Client Code**: In your application, use the prototype to create new objects by cloning the prototype object. The client code should not be responsible for creating objects from scratch but should rely on the prototype to provide new instances.
## **Example:**
Let's say you are developing a game where characters can be customized with various attributes, such as name, appearance, and abilities. Instead of creating each character from scratch, you can use the Prototype Pattern to clone a prototype character with default attributes and customize the clones as needed:
- **Prototype Interface or Abstract Class**: Define a `Character` interface or abstract class that includes a `clone` method.
```java
public interface Character {
Character clone();
void customize(String name, String appearance, String abilities);
void displayInfo();
}
```
- **Concrete Prototypes**: Create concrete character classes that implement the `Character` interface or extend the `Character` abstract class. Each class represents a specific type of character.
```java
public class Warrior implements Character {
private String name;
private String appearance;
private String abilities;
public Warrior() {
// Default attributes for a warrior
this.name = "Warrior";
this.appearance = "Strong and armored";
this.abilities = "Melee combat skills";
}
@Override
public Character clone() {
Warrior clone = new Warrior();
clone.customize(this.name, this.appearance, this.abilities);
return clone;
}
@Override
public void customize(String name, String appearance, String abilities) {
this.name = name;
this.appearance = appearance;
this.abilities = abilities;
}
@Override
public void displayInfo() {
System.out.println("Character: " + name);
System.out.println("Appearance: " + appearance);
System.out.println("Abilities: " + abilities);
}
}
// Create similar classes for other character types (e.g., Mage, Rogue)
```
- **Client Code**: In your game code, use the prototype to create new character instances and customize them as needed:
```java
Character prototype = new Warrior();
Character warrior1 = prototype.clone();
warrior1.customize("Sir Lancelot", "Shiny armor", "Swordsmanship");
Character warrior2 = prototype.clone();
warrior2.customize("Lady Guinevere", "Elegant armor", "Archery");
warrior1.displayInfo();
warrior2.displayInfo();
```
By using the Prototype Pattern, you can create new character instances by cloning the prototype, customizing them for different characters in your game, and displaying their individual attributes. This pattern promotes code reusability and flexibility when creating objects with similar initial states.

View file

@ -0,0 +1,57 @@
---
obj: concept
---
# Resource Acquisition Is Initialization (RAII)
## **Description:**
Resource Acquisition Is Initialization (RAII) is an idiom rather than a design pattern, but it's an important and widely used programming technique. RAII ties the lifetime of a resource (e.g., memory, files, locks) to the scope of an object. It ensures that the resource is automatically acquired when an object is created and automatically released when the object goes out of scope, thus preventing resource leaks and simplifying resource management.
**How it's Used:**
1. **Resource Management Class**: Create a resource management class (often referred to as a "wrapper" or "smart" class) that encapsulates the resource's allocation and deallocation logic.
2. **Constructor**: In the constructor of the resource management class, acquire the resource (e.g., allocate memory, open a file, acquire a lock).
3. **Destructor (or Dispose Method)**: In the destructor (or a dispose method for languages like C#), release the resource (e.g., deallocate memory, close a file, release a lock). The destructor is automatically called when the object goes out of scope.
4. **Use in Client Code**: In your client code, create an instance of the resource management class. The resource will be automatically acquired when the object is created and automatically released when it goes out of scope.
## **Example:**
A common example of RAII is managing dynamic memory in C++ using the `std::unique_ptr` smart pointer:
```cpp
#include <iostream>
#include <memory>
class MyResource {
public:
MyResource() {
// Acquire a resource (e.g., allocate memory)
data = new int[10];
std::cout << "Resource acquired." << std::endl;
}
~MyResource() {
// Release the resource (e.g., deallocate memory)
delete[] data;
std::cout << "Resource released." << std::endl;
}
void performOperation() {
// Perform some operation with the resource
std::cout << "Operation performed." << std::endl;
}
private:
int* data;
};
int main() {
// Create an instance of MyResource
MyResource resource;
// Use the resource
resource.performOperation();
// Resource is automatically released when 'resource' goes out of scope
return 0;
}
```
In this C++ example, the `MyResource` class acquires and releases a resource (dynamic memory) in its constructor and destructor, respectively. When you create an instance of `MyResource` in the `main` function, the resource is automatically acquired, and when `resource` goes out of scope at the end of `main`, the resource is automatically released. This ensures that you don't have to worry about explicitly managing the resource's lifecycle in your client code, reducing the risk of resource leaks.

View file

@ -0,0 +1,71 @@
---
obj: concept
---
# Singleton Pattern
## **Description:**
The Singleton Pattern is a creational design pattern that ensures a class has only one instance and provides a global point of access to that instance. It is commonly used when you want to restrict the instantiation of a class to a single object and control access to that unique instance across the application.
**How it's Used:**
1. **Private Constructor**: Ensure that the class has a private constructor to prevent direct instantiation from external code.
2. **Static Instance**: Create a static instance of the class within the class itself.
3. **Lazy or Eager Initialization**: Decide whether to initialize the instance lazily (on-demand) or eagerly (at the time of class loading). Lazy initialization is preferred if resource usage should be minimized.
4. **Static Method**: Provide a static method within the class to access the unique instance. This method should handle the creation of the instance if it doesn't exist or return the existing instance.
5. **Thread Safety (Optional)**: If your application is multithreaded, ensure that the creation of the instance and access to it is thread-safe, especially if using lazy initialization.
## **Example:**
A classic example of the Singleton Pattern is creating a configuration manager that provides access to application-wide configuration settings:
```java
public class ConfigurationManager {
private static ConfigurationManager instance; // Static instance variable
private String configurationData;
// Private constructor to prevent external instantiation
private ConfigurationManager() {
// Initialize configurationData from a configuration file or other source
configurationData = "Default configuration";
}
// Static method to provide access to the unique instance
public static ConfigurationManager getInstance() {
if (instance == null) {
instance = new ConfigurationManager(); // Lazy initialization
}
return instance;
}
public String getConfigurationData() {
return configurationData;
}
public void setConfigurationData(String data) {
configurationData = data;
}
}
```
In this Java example:
- The `ConfigurationManager` class has a private constructor to prevent external instantiation.
- It contains a private static instance variable.
- The `getInstance` static method is used to access the unique instance of the class. It initializes the instance lazily when called for the first time.
- You can use `ConfigurationManager.getInstance()` to access the configuration manager from anywhere in your application.
```java
public class Main {
public static void main(String[] args) {
ConfigurationManager configManager1 = ConfigurationManager.getInstance();
ConfigurationManager configManager2 = ConfigurationManager.getInstance();
// Both instances refer to the same unique object
System.out.println(configManager1 == configManager2); // true
// Access and modify configuration data
System.out.println(configManager1.getConfigurationData()); // Default configuration
configManager1.setConfigurationData("New configuration");
System.out.println(configManager2.getConfigurationData()); // New configuration
}
}
```
The Singleton Pattern ensures that there's only one instance of `ConfigurationManager` throughout the application, providing a centralized and controlled way to manage configuration data.

View file

@ -0,0 +1,64 @@
---
obj: concept
---
# Adapter Pattern
## **Description:**
The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to work together. It acts as a bridge between two incompatible interfaces, enabling them to collaborate without altering their source code. The Adapter Pattern is useful when you want to reuse existing classes or integrate third-party libraries that don't quite fit your desired interface.
**How it's Used:**
1. **Identify Interfaces**: Identify the two interfaces that need to work together but are incompatible.
2. **Adapter Class**: Create an adapter class that implements the interface expected by the client code (the target interface) while containing an instance of the class with the incompatible interface (the adaptee).
3. **Adapter Methods**: Within the adapter class, implement methods that map the methods of the target interface to the corresponding methods of the adaptee interface.
4. **Client Code**: In the client code, use the adapter class to interact with the adaptee class as if it implements the target interface.
## **Example:**
Suppose you have a legacy class `OldSystem` with an interface that is incompatible with your modern system, but you need to integrate the legacy functionality. Here's how the Adapter Pattern can be applied:
- **Incompatible Legacy Class (Adaptee)**: Define the `OldSystem` class with its existing interface.
```java
public class OldSystem {
public void doOldStuff() {
System.out.println("Doing old stuff in the legacy system.");
}
}
```
- **Target Interface**: Define the `NewSystem` interface that your modern system expects.
```java
public interface NewSystem {
void doNewStuff();
}
```
- **Adapter Class**: Create an adapter class `Adapter` that implements the `NewSystem` interface and contains an instance of the `OldSystem` class.
```java
public class Adapter implements NewSystem {
private OldSystem oldSystem;
public Adapter(OldSystem oldSystem) {
this.oldSystem = oldSystem;
}
@Override
public void doNewStuff() {
// Delegate the new system's request to the old system's method
oldSystem.doOldStuff();
}
}
```
- **Client Code**: In your modern system, use the `Adapter` class to work with the `OldSystem` as if it were a `NewSystem`.
```java
public class Client {
public static void main(String[] args) {
OldSystem legacySystem = new OldSystem();
NewSystem adapter = new Adapter(legacySystem);
// Use the adapter to perform new system operations
adapter.doNewStuff();
}
}
```
By using the Adapter Pattern, you can integrate the legacy `OldSystem` class seamlessly into your modern system without changing the code of the legacy class. The adapter serves as a bridge, translating calls from the new system's interface to the old system's interface, allowing them to work together.

View file

@ -0,0 +1,107 @@
---
obj: concept
---
# Bridge Pattern
## **Description:**
The Bridge Pattern is a structural design pattern that separates an object's abstraction (high-level logic) from its implementation (low-level details). It allows you to vary both the abstraction and the implementation independently, making it easier to extend and maintain complex systems. This pattern is particularly useful when you have a hierarchy of classes with multiple dimensions of variation.
**How it's Used:**
1. **Identify Abstraction and Implementation**: Identify the components of your system that have multiple dimensions of variation. This typically involves defining an abstraction (high-level logic) and one or more implementations (low-level details).
2. **Abstraction Class**: Create an abstraction class that contains a reference to an implementation object. The abstraction class defines high-level methods and delegates the implementation details to the implementation object.
3. **Implementation Interface or Abstract Class**: Define an interface or an abstract class for the implementation, which will be implemented by concrete implementation classes.
4. **Concrete Implementation Classes**: Create concrete implementation classes that implement the interface or extend the abstract class defined for the implementation. These classes contain the low-level implementation details.
5. **Client Code**: In your client code, use the abstraction class to interact with the high-level logic while providing or selecting the specific implementation at runtime.
## **Example:**
Consider a drawing application where you have different shapes (e.g., circles, rectangles) that can be drawn using different rendering techniques (e.g., vector graphics, raster graphics). Here's how the Bridge Pattern can be applied:
- **Abstraction Class**: Create an abstraction class `Shape` that contains a reference to an implementation object `Renderer`.
```java
public abstract class Shape {
protected Renderer renderer;
public Shape(Renderer renderer) {
this.renderer = renderer;
}
public abstract void draw();
}
```
- **Implementation Interface**: Define an interface `Renderer` for the rendering implementation.
```java
public interface Renderer {
void render();
}
```
- **Concrete Implementation Classes**: Create concrete implementation classes for different rendering techniques, such as `VectorRenderer` and `RasterRenderer`.
```java
public class VectorRenderer implements Renderer {
@Override
public void render() {
System.out.println("Rendering as vector graphics.");
}
}
public class RasterRenderer implements Renderer {
@Override
public void render() {
System.out.println("Rendering as raster graphics.");
}
}
```
- **Concrete Abstraction Classes**: Create concrete abstraction classes for different shapes, such as `Circle` and `Rectangle`, that extend the `Shape` class and provide specific implementations for the `draw` method.
```java
public class Circle extends Shape {
private int radius;
public Circle(Renderer renderer, int radius) {
super(renderer);
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Drawing a circle with radius " + radius);
renderer.render();
}
}
public class Rectangle extends Shape {
private int width;
private int height;
public Rectangle(Renderer renderer, int width, int height) {
super(renderer);
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println("Drawing a rectangle with width " + width + " and height " + height);
renderer.render();
}
}
```
- **Client Code**: In your application, use the abstraction classes to create shapes and specify the rendering technique at runtime.
```java
public class Client {
public static void main(String[] args) {
Renderer vectorRenderer = new VectorRenderer();
Renderer rasterRenderer = new RasterRenderer();
Shape circle = new Circle(vectorRenderer, 5);
Shape rectangle = new Rectangle(rasterRenderer, 10, 20);
circle.draw();
rectangle.draw();
}
}
```
By using the Bridge Pattern, you can vary the shapes and rendering techniques independently, making it easier to add new shapes or rendering methods without affecting existing code. This pattern promotes flexibility and maintainability in complex systems with multiple dimensions of variation.

View file

@ -0,0 +1,93 @@
---
obj: concept
---
# Composite Pattern
## **Description:**
The Composite Pattern is a structural design pattern that allows you to compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly. In other words, you can use the same interface to work with both single objects and compositions of objects. This pattern is particularly useful when dealing with hierarchical structures and you want to apply operations recursively.
**How it's Used:**
1. **Component Interface**: Define an abstract class or interface, often called `Component`, that represents the common interface for both leaf and composite objects. This interface includes methods that are common to all objects in the hierarchy.
2. **Leaf Class**: Create a leaf class that implements the `Component` interface. Leaf objects are the individual objects that do not have children in the hierarchy.
3. **Composite Class**: Create a composite class that also implements the `Component` interface. Composite objects can contain child components, including both leaf and other composite objects.
4. **Add and Remove Methods**: In the composite class, provide methods to add and remove child components. These methods allow you to build and modify the hierarchical structure dynamically.
5. **Client Code**: In your client code, work with objects through the `Component` interface. You can treat individual objects and compositions of objects uniformly, as they share a common interface.
## **Example:**
Imagine you are building a graphical user interface (GUI) library that needs to handle a hierarchy of UI elements, including individual controls (buttons, text fields) and composite elements (e.g., windows containing other controls). Here's how the Composite Pattern can be applied:
- **Component Interface**: Define an abstract `UIComponent` interface that represents the common interface for all UI element
```java
public interface UIComponent {
void render();
}
```
- **Leaf Class**: Create leaf classes like `Button` and `TextField` that implement the `UIComponent` interface.
```java
public class Button implements UIComponent {
private String label;
public Button(String label) {
this.label = label;
}
@Override
public void render() {
System.out.println("Rendered Button: " + label);
}
}
public class TextField implements UIComponent {
@Override
public void render() {
System.out.println("Rendered TextField");
}
}
```
- **Composite Class**: Create a composite class, such as `Window`, that implements the `UIComponent` interface and can contain child components.
```java
import java.util.ArrayList;
import java.util.List;
public class Window implements UIComponent {
private List<UIComponent> children = new ArrayList<>();
public void add(UIComponent component) {
children.add(component);
}
public void remove(UIComponent component) {
children.remove(component);
}
@Override
public void render() {
System.out.println("Rendered Window");
for (UIComponent child : children) {
child.render();
}
}
}
```
- **Client Code**: In your GUI library or application, create instances of leaf objects and composite objects and use them through the `UIComponent` interface.
```java
public class Client {
public static void main(String[] args) {
UIComponent button1 = new Button("OK");
UIComponent button2 = new Button("Cancel");
UIComponent textField = new TextField();
Window window = new Window();
window.add(button1);
window.add(button2);
window.add(textField);
window.render();
}
}
```
By using the Composite Pattern, you can build complex UI hierarchies by composing individual UI elements (leaf objects) and containers (composite objects). Clients can work with these elements uniformly, regardless of whether they are individual controls or nested containers. This promotes code reusability and flexibility when dealing with hierarchical structures.

View file

@ -0,0 +1,106 @@
---
obj: concept
---
# Decorator Pattern
## **Description:**
The Decorator Pattern is a structural design pattern that allows behavior to be added to individual objects, either statically or dynamically, without affecting the behavior of other objects from the same class. It is used to extend the functionality of classes in a flexible and reusable way, promoting the principle of open-closed design.
**How it's Used:**
1. **Component Interface**: Define an abstract class or interface, often called `Component`, that represents the base object's interface. This is the interface that decorators and concrete components will implement.
2. **Concrete Component**: Create a concrete component class that implements the `Component` interface. This class represents the base object to which additional behavior can be added.
3. **Decorator**: Create abstract decorator classes that also implement the `Component` interface. These classes have a reference to a `Component` object, and they can add, modify, or extend the behavior of the base component.
4. **Concrete Decorators**: Create concrete decorator classes that extend the abstract decorator classes. These classes provide specific functionality that can be added to the base component.
5. **Composition**: Use composition to combine the base component with one or more decorators. The decorators can be stacked, allowing multiple responsibilities to be added to the base component in a flexible manner.
## **Example:**
Let's say you are building a text editor application, and you want to add text formatting features like bold, italic, and underline. You can use the Decorator Pattern to add these features dynamically to the text without changing the text object itself:
- **Component Interface**: Define an interface `Text` that represents the basic text functionality.
```java
public interface Text {
String getContent();
}
```
- **Concrete Component**: Create a concrete component class `PlainText` that implements the `Text` interface.
```java
public class PlainText implements Text {
private String content;
public PlainText(String content) {
this.content = content;
}
@Override
public String getContent() {
return content;
}
}
```
- **Decorator**: Create an abstract decorator class `TextDecorator` that also implements the `Text` interface and has a reference to a `Text` object.
```java
public abstract class TextDecorator implements Text {
protected Text decoratedText;
public TextDecorator(Text decoratedText) {
this.decoratedText = decoratedText;
}
}
```
- **Concrete Decorators**: Create concrete decorator classes for formatting, such as `BoldText`, `ItalicText`, and `UnderlineText`, which extend `TextDecorator` and add specific formatting.
```java
public class BoldText extends TextDecorator {
public BoldText(Text decoratedText) {
super(decoratedText);
}
@Override
public String getContent() {
return "<b>" + decoratedText.getContent() + "</b>";
}
}
public class ItalicText extends TextDecorator {
public ItalicText(Text decoratedText) {
super(decoratedText);
}
@Override
public String getContent() {
return "<i>" + decoratedText.getContent() + "</i>";
}
}
public class UnderlineText extends TextDecorator {
public UnderlineText(Text decoratedText) {
super(decoratedText);
}
@Override
public String getContent() {
return "<u>" + decoratedText.getContent() + "</u>";
}
}
```
- **Client Code**: In your text editor application, create an instance of the base `PlainText` class and decorate it with one or more formatting decorators.
```java
public class Client {
public static void main(String[] args) {
Text text = new PlainText("Hello, world!");
// Decorate the text with formatting
text = new BoldText(text);
text = new ItalicText(text);
text = new UnderlineText(text);
// Output the formatted text
System.out.println(text.getContent());
}
}
```
By using the Decorator Pattern, you can add text formatting features to the base `PlainText` object dynamically. You can easily stack and combine different formatting decorators to achieve various formatting options without modifying the base text object's code. This pattern promotes flexibility and maintainability when extending the functionality of objects.

View file

@ -0,0 +1,66 @@
---
obj: concept
---
# Facade Pattern
## **Description:**
The Facade Pattern is a structural design pattern that provides a simplified and unified interface to a set of interfaces in a subsystem. It acts as a front-facing interface to a complex system, making it easier for clients to interact with that system. The Facade Pattern promotes loose coupling and encapsulation by hiding the complexities of the subsystem behind a simple interface.
**How it's Used:**
1. **Subsystem**: Identify a complex subsystem or set of related classes that perform various tasks but have a complex and possibly fragmented interface.
2. **Facade Class**: Create a facade class that encapsulates the subsystem's functionality and provides a simplified, high-level interface for clients.
3. **Facade Methods**: Define methods in the facade class that correspond to the common operations or workflows that clients need to perform within the subsystem.
4. **Client Code**: Clients interact with the subsystem through the facade class by calling its methods. Clients are shielded from the complexities of the subsystem.
## **Example:**
Imagine you are developing a multimedia processing library with various components for image processing, audio processing, and video processing. Each component has its own set of classes and interfaces, and interacting with them individually can be complex. You can use the Facade Pattern to create a simplified interface for clients:
- **Subsystem Classes**: Define classes for image processing, audio processing, and video processing, each with its own set of methods and complexities.
- **Facade Class**: Create a `MultimediaProcessor` facade class that provides high-level methods for common multimedia operations, such as `processImage`, `processAudio`, and `processVideo`.
```java
public class MultimediaProcessor {
private ImageProcessor imageProcessor;
private AudioProcessor audioProcessor;
private VideoProcessor videoProcessor;
public MultimediaProcessor() {
this.imageProcessor = new ImageProcessor();
this.audioProcessor = new AudioProcessor();
this.videoProcessor = new VideoProcessor();
}
public void processImage(String imagePath) {
imageProcessor.loadImage(imagePath);
imageProcessor.applyFilters();
imageProcessor.saveImage();
}
public void processAudio(String audioPath) {
audioProcessor.loadAudio(audioPath);
audioProcessor.adjustVolume();
audioProcessor.saveAudio();
}
public void processVideo(String videoPath) {
videoProcessor.loadVideo(videoPath);
videoProcessor.extractAudio();
videoProcessor.convertToFormat();
videoProcessor.saveVideo();
}
}
```
- **Client Code**: In your client code, use the `MultimediaProcessor` facade class to perform multimedia operations without needing to interact with the individual image, audio, and video processing components directly.
```java
public class Client {
public static void main(String[] args) {
MultimediaProcessor multimediaProcessor = new MultimediaProcessor();
multimediaProcessor.processImage("sample.jpg");
multimediaProcessor.processAudio("sample.mp3");
multimediaProcessor.processVideo("sample.mp4");
}
}
```
By using the Facade Pattern, you provide a simplified and unified interface (`MultimediaProcessor`) for clients to perform multimedia processing operations. Clients don't need to be aware of the individual complexities and intricacies of the subsystem components (image processing, audio processing, video processing), promoting code modularity and ease of use. The Facade Pattern is particularly valuable when dealing with complex systems or libraries with numerous components.

View file

@ -0,0 +1,84 @@
---
obj: concept
---
## Flyweight Pattern
## **Description:**
The Flyweight Pattern is a structural design pattern that is used to minimize memory usage or computational expenses by sharing as much as possible with related objects. It is particularly useful when you need to create a large number of similar objects efficiently and the objects have common, intrinsic (shared) properties and extrinsic (unique) properties that can be separated.
**How it's Used:**
1. **Identify Shared and Non-Shared Parts**: Identify the parts of objects that can be shared among multiple instances (intrinsic state) and the parts that must remain unique to each instance (extrinsic state).
2. **Flyweight Factory**: Create a flyweight factory that manages a pool of shared flyweight objects. The factory is responsible for creating and maintaining the flyweight objects.
3. **Flyweight Interface**: Define a flyweight interface that declares methods for accessing and manipulating the intrinsic state.
4. **Concrete Flyweight Classes**: Create concrete flyweight classes that implement the flyweight interface and represent the shared intrinsic state.
5. **Client Code**: In your client code, use the flyweight factory to obtain flyweight objects. For the extrinsic state (unique to each object), pass it as a parameter when requesting a flyweight object.
## **Example:**
Consider a text editor where you want to efficiently represent and display a large number of characters. Most characters share common properties like font, size, and color, while their positions and content are unique. Here's how the Flyweight Pattern can be applied:
- **Flyweight Interface**: Define a `Character` interface that represents the common properties of characters.
```java
public interface Character {
void display(int positionX, int positionY);
}
```
- **Concrete Flyweight Class**: Create a concrete flyweight class `SharedCharacter` that implements the `Character` interface and represents the shared intrinsic state (font, size, color).
```java
public class SharedCharacter implements Character {
private char symbol;
private Font font;
private int size;
private Color color;
public SharedCharacter(char symbol, Font font, int size, Color color) {
this.symbol = symbol;
this.font = font;
this.size = size;
this.color = color;
}
@Override
public void display(int positionX, int positionY) {
System.out.println("Symbol: " + symbol +
", Font: " + font.getName() +
", Size: " + size +
", Color: " + color +
", Position: (" + positionX + ", " + positionY + ")");
}
}
```
- **Flyweight Factory**: Create a flyweight factory `CharacterFactory` that manages a pool of shared flyweight objects.
```java
import java.util.HashMap;
import java.util.Map;
public class CharacterFactory {
private Map<Character, Character> characterPool = new HashMap<>();
public Character getCharacter(char symbol, Font font, int size, Color color) {
Character sharedCharacter = new SharedCharacter(symbol, font, size, color);
characterPool.put(symbol, sharedCharacter);
return sharedCharacter;
}
}
```
- **Client Code**: In your client code, use the `CharacterFactory` to obtain flyweight objects and pass the unique extrinsic state (position) as a parameter when displaying characters.
```java
public class Client {
public static void main(String[] args) {
CharacterFactory characterFactory = new CharacterFactory();
// Display characters at different positions with shared properties
Character charA = characterFactory.getCharacter('A', Font.BOLD, 12, Color.BLACK);
charA.display(10, 20);
Character charB = characterFactory.getCharacter('B', Font.ITALIC, 14, Color.RED);
charB.display(30, 40);
}
}
```
By using the Flyweight Pattern, you efficiently represent a large number of characters while sharing common properties, thus reducing memory usage. The extrinsic state (position) remains unique to each character instance, and the pattern helps manage shared and non-shared aspects effectively. This pattern is especially valuable in scenarios where many objects have a significant amount of shared state.

View file

@ -0,0 +1,83 @@
---
obj: concept
---
# Proxy Pattern
## **Description:**
The Proxy Pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. It allows you to create a level of indirection to an object, which can be useful for various purposes such as controlling access, lazy loading, logging, monitoring, or adding a security layer to the real object.
**How it's Used:**
1. **Real Subject**: Define an interface that both the real subject and the proxy implement. This interface represents the common operations that the real subject and proxy can perform.
2. **Proxy Class**: Create a proxy class that implements the same interface as the real subject. This proxy class contains a reference to the real subject.
3. **Proxy Methods**: In the proxy methods, you can add additional behavior before or after delegating the request to the real subject. This additional behavior can include access control, logging, or lazy loading.
4. **Client Code**: Clients interact with the proxy object, thinking it's the real subject. The proxy object handles the interaction with the real subject.
## **Example:**
Consider a scenario where you have a large collection of images, and you want to load and display them only when needed to improve performance. You can use the Proxy Pattern to implement lazy loading:
- **Subject Interface**: Define an interface `Image` that represents the common operations for images.
```java
public interface Image {
void display();
}
```
- **Real Subject**: Create a real subject class `RealImage` that implements the `Image` interface. This class represents the actual image and loads it when required.
```java
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
```
- **Proxy Class**: Create a proxy class `ProxyImage` that also implements the `Image` interface. This class contains a reference to the real image but loads it lazily when requested.
```java
public class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
```
- **Client Code**: In your client code, use the `ProxyImage` class to interact with images. Images are loaded and displayed only when the `display` method is called.
```java
public class Client {
public static void main(String[] args) {
Image image1 = new ProxyImage("image1.jpg");
Image image2 = new ProxyImage("image2.jpg");
// Images are loaded and displayed when requested
image1.display();
image2.display();
// No additional loading for the already displayed image
image1.display();
}
}
```
By using the Proxy Pattern, you can improve the performance of your application by loading and displaying images lazily. The proxy object (`ProxyImage`) handles the loading and displaying of the real images (`RealImage`) as needed. This pattern is also useful for scenarios where you need to control access to sensitive resources, log actions, or add additional functionality to an object without changing its core behavior.