(T value, {required int size}) {
+ late ByteData byteData;
+
+ if (size == 1) {
+ byteData = ByteData(1)..setInt8(0, value as int);
+ } else {
+ byteData = ByteData(size);
+ if (value is double) {
+ byteData.setFloat64(0, value);
+ } else if (value is int) {
+ byteData.setInt64(0, value);
+ }
+ }
+
+ final bytes = byteData.buffer.asUint8List();
+ return bytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join(' ');
+ }
+}
diff --git a/patterns/strategy/view_strategy/strategies/str_view_strategy.dart b/patterns/strategy/view_strategy/strategies/str_view_strategy.dart
new file mode 100644
index 0000000..b9aa9bb
--- /dev/null
+++ b/patterns/strategy/view_strategy/strategies/str_view_strategy.dart
@@ -0,0 +1,9 @@
+import '../pattern/byte_context.dart';
+import '../pattern/view_strategy.dart';
+
+class StrViewStrategy implements ViewStrategy {
+ @override
+ String out(ByteContext byteList) {
+ return '${byteList.toList().join(', ')}\n';
+ }
+}
diff --git a/patterns/strategy/view_strategy/strategies/zip_view_strategy.dart b/patterns/strategy/view_strategy/strategies/zip_view_strategy.dart
new file mode 100644
index 0000000..7e78645
--- /dev/null
+++ b/patterns/strategy/view_strategy/strategies/zip_view_strategy.dart
@@ -0,0 +1,25 @@
+import 'dart:io';
+
+import '../pattern/byte_context.dart';
+import 'str_view_strategy.dart';
+
+class ZipViewStrategy extends StrViewStrategy {
+ @override
+ String out(ByteContext byteList) {
+ final codes = super.out(byteList).codeUnits;
+ final bytes = GZipCodec().encode(codes);
+ final buf = StringBuffer();
+
+ var odd = 1;
+ for (final byte in bytes) {
+ final hexByte = byte.toRadixString(16).padLeft(2, '0');
+ buf.write('$hexByte ');
+
+ if (odd++ % 16 == 0) {
+ buf.writeln();
+ }
+ }
+
+ return buf.toString();
+ }
+}
diff --git a/patterns/template_method/data_miner/README.md b/patterns/template_method/data_miner/README.md
new file mode 100644
index 0000000..c3e1815
--- /dev/null
+++ b/patterns/template_method/data_miner/README.md
@@ -0,0 +1,73 @@
+# Template Method Pattern
+Template Method is a behavioral design pattern that defines the skeleton of an algorithm in the
+superclass but lets subclasses override specific steps of the algorithm without changing its
+structure.
+
+Tutorial: [here](https://refactoring.guru/design-patterns/template-method).
+
+## Diagram:
+![image](https://user-images.githubusercontent.com/8049534/174060908-402eea9b-a030-4e45-8e95-54cfcac61bb6.png)
+
+### Client code:
+```dart
+void main() {
+ print('HTMLMiner');
+ HTMLMiner('google_workers.html').mine();
+
+ print('CsvMiner');
+ CsvMiner('twitter_workers.csv').mine();
+
+ print('GuruMiner');
+ ZipMiner('refactoring_guru_workers.zip').mine();
+}
+```
+
+### Output:
+```
+HTMLMiner
+ Name Index
+-------------------------------
+ Ayana White 33.92
+ Dillan Ewing 6.21
+ Kimora Arroyo 84.7
+ Aspen Simmons 93.08
+ Giana Perry 67.56
+ Luz Carson 69.88
+ Kaleb Pineda 47.87
+ Kianna Bautista 3.09
+ Jorge Reeves 16.52
+ Leroy Morrow 51.24
+ Ashlyn Crawford 7.25
+ Yasmine Hampton 38.42
+-------------------------------
+ sum: 519.74
+ len: 12
+
+CsvMiner
+ Name Index
+-------------------------------
+ Laylah Whitehead 22.1
+ Karissa Arellano 2.0
+ Maggie Mcmahon 12.25
+ Ariel Bartlett 8.1
+ Rashad Herman 5.8
+ Rachael Hickman 5.22
+ Tara Spence 9.48
+ Kiera Cervantes 4.0
+ Shane Robertson 9.0
+ Perla Yoder 67.3
+-------------------------------
+ sum: 145.25
+ len: 10
+
+ZipMiner
+ Name Index
+-------------------------------
+ Dmitry Zhart 62.4
+ Alexander Shvets 44.6
+ Fishchenko Ilya 1.4
+-------------------------------
+ sum: 108.4
+ len: 3
+```
+
diff --git a/patterns/template_method/data_miner/main.dart b/patterns/template_method/data_miner/main.dart
new file mode 100644
index 0000000..879d0fa
--- /dev/null
+++ b/patterns/template_method/data_miner/main.dart
@@ -0,0 +1,15 @@
+import 'miners/csv_miner.dart';
+import 'miners/zip_miner.dart';
+import 'miners/html_analyzer.dart';
+
+void main() {
+ print('HTMLMiner');
+ HTMLMiner('google_workers.html').mine();
+
+ print('CsvMiner');
+ CsvMiner('twitter_workers.csv').mine();
+
+ print('GuruMiner');
+ ZipMiner('refactoring_guru_workers.zip').mine();
+}
+
diff --git a/patterns/template_method/data_miner/miners/csv_miner.dart b/patterns/template_method/data_miner/miners/csv_miner.dart
new file mode 100644
index 0000000..efb849c
--- /dev/null
+++ b/patterns/template_method/data_miner/miners/csv_miner.dart
@@ -0,0 +1,11 @@
+import '../pattern/data_miner.dart';
+import '../utils/raw_data.dart';
+
+class CsvMiner extends DataMiner {
+ CsvMiner(super.fileName);
+
+ @override
+ StringTable parseData(RawData raw) {
+ return raw.split('\n').map((line) => line.split(',')).toList();
+ }
+}
diff --git a/patterns/template_method/data_miner/miners/html_analyzer.dart b/patterns/template_method/data_miner/miners/html_analyzer.dart
new file mode 100644
index 0000000..674e872
--- /dev/null
+++ b/patterns/template_method/data_miner/miners/html_analyzer.dart
@@ -0,0 +1,23 @@
+import '../pattern/data_miner.dart';
+import '../utils/raw_data.dart';
+
+class HTMLMiner extends DataMiner {
+ HTMLMiner(super.fileName);
+
+ @override
+ StringTable parseData(RawData raw) {
+ String regexString = r']+>(.+)<\/td>'
+ r'\s+'
+ r' | ]+>(.+)<\/td>';
+ final regExp = RegExp(regexString);
+ final matches = regExp.allMatches(raw);
+
+ return [
+ for (final employer in matches)
+ [
+ employer.group(1)!,
+ employer.group(2)!,
+ ]
+ ];
+ }
+}
diff --git a/patterns/template_method/data_miner/miners/zip_miner.dart b/patterns/template_method/data_miner/miners/zip_miner.dart
new file mode 100644
index 0000000..b98d6b3
--- /dev/null
+++ b/patterns/template_method/data_miner/miners/zip_miner.dart
@@ -0,0 +1,33 @@
+import 'dart:io';
+
+import '../pattern/data_miner.dart';
+import '../utils/raw_data.dart';
+
+class ZipMiner extends DataMiner {
+ ZipMiner(super.fileName);
+
+ @override
+ RawData extractData(File file) {
+ final content = File('${reportPath}refactoring_guru_workers.zip')
+ .readAsBytesSync()
+ .toList();
+ final unzip = GZipCodec().decode(content);
+ return String.fromCharCodes(unzip);
+ }
+
+ @override
+ StringTable parseData(RawData raw) {
+ final lines = raw.split('\n');
+ final divIndex = lines.length ~/ 2;
+ final names = lines.sublist(0, divIndex);
+ final indexes = lines.sublist(divIndex);
+
+ return [
+ for (var i = 0; i < divIndex; i++)
+ [
+ names[i].trim(),
+ indexes[i].trim(),
+ ]
+ ];
+ }
+}
diff --git a/patterns/template_method/data_miner/pattern/data_miner.dart b/patterns/template_method/data_miner/pattern/data_miner.dart
new file mode 100644
index 0000000..1600972
--- /dev/null
+++ b/patterns/template_method/data_miner/pattern/data_miner.dart
@@ -0,0 +1,71 @@
+import 'dart:io';
+
+import '../utils/analysis.dart';
+import '../utils/formatted_table.dart';
+import '../utils/raw_data.dart';
+
+abstract class DataMiner {
+ final String fileName;
+
+ DataMiner(this.fileName);
+
+ void mine() {
+ final file = openFile();
+ final raw = extractData(file);
+ final table = parseData(raw);
+ final analysis = analyzeData(table);
+ sendReport(analysis, table);
+ }
+
+ File openFile() {
+ final file = File(reportPath + fileName);
+
+ if (!file.existsSync()) {
+ throw 'File not exists.';
+ }
+
+ return file;
+ }
+
+ RawData extractData(File file) {
+ return file.readAsStringSync();
+ }
+
+ StringTable parseData(RawData raw);
+
+ Analysis analyzeData(StringTable table) {
+ return Analysis(table);
+ }
+
+ void sendReport(Analysis analysis, StringTable table) {
+ final formattedTable = FormattedTable();
+
+ formattedTable
+ ..addRow('Name', 'Index')
+ ..addLine();
+
+ for (final row in table) {
+ final name = row[0];
+ final index = double.parse(row[1]);
+
+ formattedTable.addRow(name, index);
+ }
+
+ formattedTable
+ ..addLine()
+ ..addRow('sum:', analysis.sum)
+ ..addRow('len:', analysis.len);
+
+ print(formattedTable.toString());
+ }
+
+ String get reportPath => '${Platform.script.pathSegments.sublist(
+ 0,
+ Platform.script.pathSegments.length - 1,
+ ).join(
+ Platform.pathSeparator,
+ )}'
+ '${Platform.pathSeparator}'
+ 'reports'
+ '${Platform.pathSeparator}';
+}
diff --git a/patterns/template_method/data_miner/reports/google_workers.html b/patterns/template_method/data_miner/reports/google_workers.html
new file mode 100644
index 0000000..660be3a
--- /dev/null
+++ b/patterns/template_method/data_miner/reports/google_workers.html
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+ A |
+ B |
+
+
+
+
+
+ Ayana White |
+ 33.92 |
+
+
+
+ Dillan Ewing |
+ 6.21 |
+
+
+
+ Kimora Arroyo |
+ 84.7 |
+
+
+
+ Aspen Simmons |
+ 93.08 |
+
+
+
+ Giana Perry |
+ 67.56 |
+
+
+
+ Luz Carson |
+ 69.88 |
+
+
+
+ Kaleb Pineda |
+ 47.87 |
+
+
+
+ Kianna Bautista |
+ 3.09 |
+
+
+
+ Jorge Reeves |
+ 16.52 |
+
+
+
+ Leroy Morrow |
+ 51.24 |
+
+
+
+ Ashlyn Crawford |
+ 7.25 |
+
+
+
+ Yasmine Hampton |
+ 38.42 |
+
+
+
+
diff --git a/patterns/template_method/data_miner/reports/refactoring_guru_workers.zip b/patterns/template_method/data_miner/reports/refactoring_guru_workers.zip
new file mode 100644
index 0000000..9d5afd4
Binary files /dev/null and b/patterns/template_method/data_miner/reports/refactoring_guru_workers.zip differ
diff --git a/patterns/template_method/data_miner/reports/twitter_workers.csv b/patterns/template_method/data_miner/reports/twitter_workers.csv
new file mode 100644
index 0000000..29796d9
--- /dev/null
+++ b/patterns/template_method/data_miner/reports/twitter_workers.csv
@@ -0,0 +1,10 @@
+Laylah Whitehead,22.1
+Karissa Arellano,2
+Maggie Mcmahon,12.25
+Ariel Bartlett,8.1
+Rashad Herman,5.8
+Rachael Hickman,5.22
+Tara Spence,9.48
+Kiera Cervantes,4
+Shane Robertson,9
+Perla Yoder,67.3
\ No newline at end of file
diff --git a/patterns/template_method/data_miner/utils/analysis.dart b/patterns/template_method/data_miner/utils/analysis.dart
new file mode 100644
index 0000000..e8f4e81
--- /dev/null
+++ b/patterns/template_method/data_miner/utils/analysis.dart
@@ -0,0 +1,24 @@
+import 'raw_data.dart';
+
+class Analysis {
+ Analysis(StringTable table) {
+ _analyze(table);
+ }
+
+ void _analyze(StringTable table) {
+ int len = 0;
+ double sum = 0.0;
+
+ for (final row in table) {
+ final index = double.parse(row[1]);
+ sum += index;
+ len++;
+ }
+
+ this.len = len;
+ this.sum = sum;
+ }
+
+ late final int len;
+ late final double sum;
+}
diff --git a/patterns/template_method/data_miner/utils/formatted_table.dart b/patterns/template_method/data_miner/utils/formatted_table.dart
new file mode 100644
index 0000000..0d1461d
--- /dev/null
+++ b/patterns/template_method/data_miner/utils/formatted_table.dart
@@ -0,0 +1,18 @@
+class FormattedTable {
+ void addRow(a, b) {
+ _buff.writeln(
+ '${' ' * 1}${a.padRight(20)}${b.toString().padLeft(7)}',
+ );
+ }
+
+ void addLine() {
+ _buff.writeln('-' * 31);
+ }
+
+ @override
+ String toString() {
+ return _buff.toString();
+ }
+
+ final _buff = StringBuffer();
+}
diff --git a/patterns/template_method/data_miner/utils/raw_data.dart b/patterns/template_method/data_miner/utils/raw_data.dart
new file mode 100644
index 0000000..2143126
--- /dev/null
+++ b/patterns/template_method/data_miner/utils/raw_data.dart
@@ -0,0 +1,2 @@
+typedef RawData = String;
+typedef StringTable = List>;
diff --git a/patterns/visitor/conceptual/README.md b/patterns/visitor/conceptual/README.md
new file mode 100644
index 0000000..fef872e
--- /dev/null
+++ b/patterns/visitor/conceptual/README.md
@@ -0,0 +1,82 @@
+# Visitor pattern
+Visitor is a behavioral design pattern that lets you separate algorithms from the objects on which
+they operate.
+
+Tutorial: [here](https://refactoring.guru/design-patterns/visitor).
+
+### About example.
+
+## Client code:
+### Before:
+```dart
+void main() {
+ final list = createElements();
+ list.forEach(operation1);
+}
+
+Iterable |