diff --git a/CHANGELOG.md b/CHANGELOG.md index fea0c92..72f9145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.30.0 +- Add strategy pattern: View Strategy. + ## 0.29.0 - Add conceptual visitor pattern. diff --git a/README.md b/README.md index a93a531..ae35cd7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ It contains **Dart** examples for all classic **GoF** design patterns. - [x] **State** - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/state/three_state)] [[![16x16](https://user-images.githubusercontent.com/8049534/171852337-57db0faf-1f5e-489a-a79a-22ed4f47b4ed.png) State Manipulator](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/state/manipulator_state)] - [x] **Template Method** - [[Data Miner](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/template_method/data_miner)] - [X] **Visitor** - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/visitor/conceptual)] [[Shape XML Exporter](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/visitor/shapes_exporter)] - - [X] **Strategy** [[Reservation Cargo Spaces](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/reservation_cargo_spaces)] + - [X] **Strategy** [[View Strategy](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/view_strategy)] [[Reservation Cargo Spaces](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/reservation_cargo_spaces)] - [ ] **Structural** - [x] **Adapter** - [[Text Graphics](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/text_graphics)] [[Square Round conflict](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/square_round_conflict)] [[![16x16](https://user-images.githubusercontent.com/8049534/171852337-57db0faf-1f5e-489a-a79a-22ed4f47b4ed.png) Flutter Adapter](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/flutter_adapter)] - [x] **Bridge** - [[Remote Device Control](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/bridge/devices_remote_control)] [[Clock](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/bridge/clock)] diff --git a/patterns/strategy/view_strategy/README.md b/patterns/strategy/view_strategy/README.md new file mode 100644 index 0000000..ad2abd8 --- /dev/null +++ b/patterns/strategy/view_strategy/README.md @@ -0,0 +1,43 @@ +# Strategy Pattern +Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of +them into a separate class, and make their objects interchangeable. + +Tutorial: [here](https://refactoring.guru/design-patterns/strategy). + +## Diagram: +![image](https://user-images.githubusercontent.com/8049534/175562829-c91fbb12-50ac-4373-a33f-900527383a6c.png) + +## Client code: +```dart +void main() { + final byteList = ByteContext() + ..add('Hello guru') + ..add(123456789) + ..add(3.1456564984); + + final strFormat = byteList.toStringView(StrViewStrategy()); + final hexFormat = byteList.toStringView(HexViewStrategy()); + final zipFormat = byteList.toStringView(ZipViewStrategy()); + + print(strFormat); + print(hexFormat); + print(zipFormat); +} +``` + +### Output: +``` +StrViewStrategy: +Hello guru, 123456789, 3.1456564984 + +HexViewStrategy: +Hello guru : 48 65 6c 6c 6f 20 67 75 72 75 +123456789 : 00 00 00 00 07 5b cd 15 +3.1456564984 : 40 09 2a 4d f4 48 9f 7e + +ZipViewStrategy: +1f 8b 08 00 00 00 00 00 00 0a f3 48 cd c9 c9 57 +48 2f 2d 2a d5 51 30 34 32 36 31 35 33 b7 b0 d4 +51 30 d6 33 04 32 4d cd 4c 2c 2d 4c b8 00 d4 70 +cf ee 24 00 00 00 +``` diff --git a/patterns/strategy/view_strategy/main.dart b/patterns/strategy/view_strategy/main.dart new file mode 100644 index 0000000..fe343f4 --- /dev/null +++ b/patterns/strategy/view_strategy/main.dart @@ -0,0 +1,19 @@ +import 'pattern/byte_context.dart'; +import 'strategies/hex_view_strategy.dart'; +import 'strategies/str_view_strategy.dart'; +import 'strategies/zip_view_strategy.dart'; + +void main() { + final byteList = ByteContext() + ..add('Hello guru') + ..add(123456789) + ..add(3.1456564984); + + final strFormat = byteList.toStringView(StrViewStrategy()); + final hexFormat = byteList.toStringView(HexViewStrategy()); + final zipFormat = byteList.toStringView(ZipViewStrategy()); + + print(strFormat); + print(hexFormat); + print(zipFormat); +} diff --git a/patterns/strategy/view_strategy/pattern/byte_context.dart b/patterns/strategy/view_strategy/pattern/byte_context.dart new file mode 100644 index 0000000..962d45c --- /dev/null +++ b/patterns/strategy/view_strategy/pattern/byte_context.dart @@ -0,0 +1,16 @@ +import 'view_strategy.dart'; + +class ByteContext { + String toStringView(ViewStrategy strategy) { + return '${strategy.runtimeType}:\n' + '${strategy.out(this)}'; + } + + void add(dynamic value) { + _buf.add(value); + } + + List toList() => _buf; + + final _buf = []; +} diff --git a/patterns/strategy/view_strategy/pattern/view_strategy.dart b/patterns/strategy/view_strategy/pattern/view_strategy.dart new file mode 100644 index 0000000..4b785ec --- /dev/null +++ b/patterns/strategy/view_strategy/pattern/view_strategy.dart @@ -0,0 +1,5 @@ +import 'byte_context.dart'; + +abstract class ViewStrategy { + String out(ByteContext byteList); +} diff --git a/patterns/strategy/view_strategy/strategies/hex_view_strategy.dart b/patterns/strategy/view_strategy/strategies/hex_view_strategy.dart new file mode 100644 index 0000000..408d276 --- /dev/null +++ b/patterns/strategy/view_strategy/strategies/hex_view_strategy.dart @@ -0,0 +1,47 @@ +import 'dart:typed_data'; + +import '../pattern/byte_context.dart'; +import '../pattern/view_strategy.dart'; + +class HexViewStrategy implements ViewStrategy { + @override + String out(ByteContext byteList) { + final buf = StringBuffer(); + + for (final val in byteList.toList()) { + buf.write('${val.toString().padRight(15)}: '); + + if (val is String) { + buf.writeln(_stringToHex(val)); + } else { + buf.writeln(_valueToHex(val, size: 8)); + } + } + + return buf.toString(); + } + + String _stringToHex(String value) { + return value.codeUnits + .map((charCode) => _valueToHex(size: 1, charCode)) + .join(' '); + } + + String _valueToHex(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/pubspec.yaml b/pubspec.yaml index 18c1e3d..ca5e20d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: design_patterns_dart description: Dart examples for all classic GoF design patterns. -version: 0.29.0 +version: 0.30.0 homepage: https://refactoring.guru/design-patterns repository: https://github.com/RefactoringGuru/design-patterns-dart issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue