Skip to content

Commit 9af1a4e

Browse files
Design patterns
Completed all design patterns.
0 parents  commit 9af1a4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2264
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
///
2+
/// Implementing a validation logic for a client to reach a ordering system.
3+
///
4+
///
5+
6+
// signature of handler
7+
abstract class BaseHandler {
8+
void setNext(BaseHandler handler);
9+
void handleRequest(Map<String, dynamic> data);
10+
}
11+
12+
void main() {
13+
BaseHandler handlerA = CheckForIPRequest();
14+
BaseHandler handlerB = AuthenticateUser();
15+
BaseHandler handlerC = ConnectToService();
16+
handlerB.setNext(handlerC);
17+
handlerA.setNext(handlerB);
18+
19+
handlerA.handleRequest({"user": "Kaushal"});
20+
handlerA.handleRequest({"user": "Kaushal"});
21+
handlerA.handleRequest({"user": "Kaushal"});
22+
handlerA.handleRequest({"user": "Kaushal"});
23+
}
24+
25+
class ConcreteHandler extends BaseHandler {
26+
BaseHandler? nextHandler;
27+
28+
@override
29+
void setNext(BaseHandler handler) {
30+
this.nextHandler = handler;
31+
}
32+
33+
@override
34+
void handleRequest(Map<String, dynamic> data) {}
35+
}
36+
37+
class CheckForIPRequest extends ConcreteHandler {
38+
int count = 0;
39+
@override
40+
void handleRequest(Map<String, dynamic> data) {
41+
count++;
42+
if (count < 3) {
43+
print('checked for api request | count: $count ');
44+
if (nextHandler != null) {
45+
nextHandler?.handleRequest(data);
46+
} else {
47+
print('next handler not assigned');
48+
}
49+
} else {
50+
print('API request blocked due to mutiple requests');
51+
}
52+
super.handleRequest(data);
53+
}
54+
}
55+
56+
class AuthenticateUser extends ConcreteHandler {
57+
@override
58+
void handleRequest(Map<String, dynamic> data) {
59+
if (data['user'] != null) {
60+
// perform auth logic
61+
print("authenticated user ${data['user']}");
62+
63+
if (nextHandler != null) {
64+
nextHandler?.handleRequest(data);
65+
} else {
66+
print('next handler not assigned');
67+
}
68+
} else {
69+
print("User not authorized");
70+
}
71+
super.handleRequest(data);
72+
}
73+
}
74+
75+
class ConnectToService extends ConcreteHandler {
76+
@override
77+
void handleRequest(Map<String, dynamic> data) {
78+
print('provided access to data');
79+
if (nextHandler != null) {
80+
nextHandler?.handleRequest(data);
81+
} else {
82+
print('next handler not assigned');
83+
}
84+
super.handleRequest(data);
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Chain of Responsibility
2+
3+
4+
### About
5+
This design solves the problem of multiple checks needed to be performed before performing a task or passing the data/request from one component to another.
6+
7+
When creating multiple requests and linking those requests, it creates a huge complex linked system and chaning one check may alter a complete link of checks which can alter the beahaviour to unknown.
8+
9+
### Solution
10+
This solution says that assume all those checks are a stand alone classes with similar signature and one handler may or maynot have reference to next handler in line.
11+
12+
13+
### Structure
14+
15+
- a base class which will act as a signature to request handlers.
16+
- Concrete classes for the base class.
17+
- client logic for chaining the responsibilities.
18+
19+
20+
I have implemented a request chain which lets user to connect to some service.
21+
It first checks for the IP request count, then it lets autheticate user,
22+
and finally lets user to connect to service.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// command class
2+
abstract class Command {
3+
void execute();
4+
void undo();
5+
}
6+
7+
// receiver
8+
class TextEditor {
9+
String _text = '';
10+
11+
void setText(String text) {
12+
this._text = text;
13+
print('$_text');
14+
}
15+
16+
String getText() {
17+
return _text;
18+
}
19+
20+
void insertText(String text) {
21+
this._text += text;
22+
print('$_text');
23+
}
24+
25+
void removeText(String text) {
26+
_text.replaceAll(text, '');
27+
print('$_text');
28+
}
29+
}
30+
31+
// Sender
32+
class TextUI {
33+
Command? _command;
34+
35+
void setCommand(Command command) {
36+
_command = command;
37+
}
38+
39+
void execute() {
40+
print('execute $_command');
41+
_command?.execute();
42+
}
43+
44+
void undo() {
45+
print('undo $_command');
46+
_command?.undo();
47+
}
48+
}
49+
50+
// concrete implementations
51+
class CutCommand implements Command {
52+
String text = '';
53+
final TextEditor _editor;
54+
55+
CutCommand({required TextEditor editor}) : _editor = editor;
56+
@override
57+
void execute() {
58+
this.text = _editor.getText();
59+
_editor.setText('');
60+
}
61+
62+
@override
63+
void undo() {
64+
_editor.insertText(text);
65+
text = '';
66+
}
67+
}
68+
69+
class PasteCommand implements Command {
70+
String text;
71+
final TextEditor _editor;
72+
73+
String olderText = '';
74+
75+
PasteCommand({required TextEditor editor, required this.text})
76+
: _editor = editor;
77+
@override
78+
void execute() {
79+
olderText = _editor.getText();
80+
_editor.insertText(text);
81+
}
82+
83+
@override
84+
void undo() {
85+
_editor.setText(olderText);
86+
}
87+
}
88+
89+
void main() {
90+
TextUI textUI = TextUI();
91+
final textEditor = TextEditor();
92+
93+
textUI.setCommand(PasteCommand(editor: textEditor, text: 'Paste this text'));
94+
textUI.execute();
95+
textUI.setCommand(CutCommand(editor: textEditor));
96+
textUI.execute();
97+
textUI.undo();
98+
}

behavioral/command_pattern/readme.md

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Command Pattern
2+
3+
4+
### About
5+
This design principle is needed when you want to decouple the sender (an object which wants to perform some execution) to the receiver (an object which will actually execute it). And treating an operation as a stand alone object with its params.
6+
7+
Why decoupling is needed in first place? Ther are many reasons for that.
8+
9+
First is that your client /sender does not need to worry about the paramters to pass when trying to execute and operation,
10+
11+
Second you can store the operations that has been performed and can revert back.
12+
13+
You can also maintian a queue for the sequnce of operations that needed to be perfomed.
14+
15+
16+
17+
### Structure
18+
19+
- A command class which has an abstraction of the execute method.
20+
- Concrete command class with their implementations, paramters required for execution and instance of Receiver class.
21+
- Client/Sender class which wants to execure something, it should hold instance of a command object.
22+
23+
24+
I have implemented a text editor with undoable operation.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
abstract class CustomIterator<T> {
2+
bool hasNext();
3+
T? next();
4+
}
5+
6+
abstract class Aggregator<T> {
7+
CustomIterator<T> getIterator();
8+
}
9+
10+
class StringIterator implements CustomIterator<String> {
11+
final List<String> items;
12+
int pos = 0;
13+
14+
StringIterator({required this.items});
15+
@override
16+
bool hasNext() {
17+
if (pos == items.length) {
18+
return false;
19+
}
20+
return true;
21+
}
22+
23+
@override
24+
String? next() {
25+
if (pos < items.length) {
26+
var item = items[pos];
27+
pos++;
28+
return item;
29+
}
30+
return null;
31+
}
32+
}
33+
34+
class IntIterator implements CustomIterator<int> {
35+
int pos = 0;
36+
final List<int> items;
37+
38+
IntIterator({required this.items});
39+
@override
40+
bool hasNext() {
41+
if (pos == items.length) {
42+
return false;
43+
}
44+
return true;
45+
}
46+
47+
@override
48+
int? next() {
49+
if (pos < items.length) {
50+
var item = items[pos];
51+
52+
pos++;
53+
return item;
54+
}
55+
return null;
56+
}
57+
}
58+
59+
class StringAggregator implements Aggregator<String> {
60+
List<String> items = [];
61+
62+
@override
63+
CustomIterator<String> getIterator() {
64+
return StringIterator(items: items);
65+
}
66+
67+
void addItem(String item) {
68+
items.add(item);
69+
}
70+
}
71+
72+
class IntAggregator implements Aggregator<int> {
73+
List<int> items = [];
74+
@override
75+
CustomIterator<int> getIterator() {
76+
return IntIterator(items: items);
77+
}
78+
79+
void addItem(int item) {
80+
items.add(item);
81+
}
82+
}
83+
84+
void main() {
85+
var aggregator = StringAggregator();
86+
87+
aggregator.addItem('1');
88+
aggregator.addItem('2');
89+
aggregator.addItem('3');
90+
var iterator = aggregator.getIterator();
91+
92+
while (iterator.hasNext()) {
93+
print(iterator.next());
94+
}
95+
96+
var aggregator2 = IntAggregator();
97+
98+
aggregator2.addItem(1);
99+
aggregator2.addItem(2);
100+
aggregator2.addItem(3);
101+
var iterator2 = aggregator2.getIterator();
102+
103+
while (iterator2.hasNext()) {
104+
print(iterator2.next());
105+
}
106+
}

behavioral/iterator_pattern/readme.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
## Iterator Pattern
2+
3+
### About
4+
This pattern provides an interface to iterate through the elements of the collection whose way of implementtion is kept hidden.
5+
6+
7+
### Structure
8+
- An iterator interface which has `hasNext()` and `next()` which retrives the next method.
9+
- Concrete implementation of iterator.
10+
- Aggregator which has creates the iterator and which holds the collection to be traveresed.
11+
12+
Currently i have implemented basic list based iterators.
13+
14+
15+

0 commit comments

Comments
 (0)