mirror of
https://github.com/farcasclaudiu/design_pattens.git
synced 2026-06-28 23:01:44 +03:00
strategy design pattern
This commit is contained in:
+3
-1
@@ -21,6 +21,7 @@ using design_patterns.behavioral.mediator;
|
|||||||
using design_patterns.behavioral.memento;
|
using design_patterns.behavioral.memento;
|
||||||
using design_patterns.behavioral.observer;
|
using design_patterns.behavioral.observer;
|
||||||
using design_patterns.behavioral.state;
|
using design_patterns.behavioral.state;
|
||||||
|
using design_patterns.behavioral.strategy;
|
||||||
|
|
||||||
namespace design_patterns
|
namespace design_patterns
|
||||||
{
|
{
|
||||||
@@ -55,7 +56,8 @@ namespace design_patterns
|
|||||||
// await MediatorSample.Run();
|
// await MediatorSample.Run();
|
||||||
// await MementoSample.Run();
|
// await MementoSample.Run();
|
||||||
// await ObserverSample.Run();
|
// await ObserverSample.Run();
|
||||||
await StateSample.Run();
|
// await StateSample.Run();
|
||||||
|
await StrategySample.Run();
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (System.Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,283 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace design_patterns.behavioral.strategy
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// Use it when:
|
||||||
|
/// - you want to use different variants of an algorithm
|
||||||
|
/// within an object and be able to switch from one algorithm
|
||||||
|
/// to another during runtime.
|
||||||
|
/// - you have a lot of similar classes that only differ
|
||||||
|
/// in the way they execute some behavior.
|
||||||
|
/// - to isolate the business logic of a class from the
|
||||||
|
/// implementation details of algorithms that may not be as important
|
||||||
|
/// in the context of that logic.
|
||||||
|
/// - your class has a massive conditional operator that switches
|
||||||
|
/// between different variants of the same algorithm.
|
||||||
|
/// </summary>
|
||||||
|
public class StrategySample
|
||||||
|
{
|
||||||
|
public static async Task Run()
|
||||||
|
{
|
||||||
|
Console.WriteLine("Behavioral - Strategy");
|
||||||
|
|
||||||
|
var processor = new SqlBuilderProcessor(new SqliteStrategy());
|
||||||
|
processor.Select.AddRange(new string[]{"fieldA", "fieldB" });
|
||||||
|
processor.From = "TableABC";
|
||||||
|
processor.Where = new LogicExpression {
|
||||||
|
First = new LogicExpression {
|
||||||
|
First = "fieldF",
|
||||||
|
Operator = LogicOperator.Equal,
|
||||||
|
Last = 1
|
||||||
|
},
|
||||||
|
Operator = LogicOperator.And,
|
||||||
|
Last = true
|
||||||
|
};
|
||||||
|
processor.Orderby.Add(("fieldA", OrderDirection.ASC));
|
||||||
|
processor.Orderby.Add(("fieldC", OrderDirection.DESC));
|
||||||
|
System.Console.WriteLine(processor);
|
||||||
|
|
||||||
|
// second strategy
|
||||||
|
processor.SetStrategy(new MsSqlStrategy());
|
||||||
|
System.Console.WriteLine(processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ISqlStrategy {
|
||||||
|
string Select(IProcessor processor);
|
||||||
|
string From(IProcessor processor);
|
||||||
|
string Where(IProcessor processor);
|
||||||
|
string OrderBy(IProcessor processor);
|
||||||
|
string GetOperatorSymbol(LogicOperator op);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OrderDirection {
|
||||||
|
ASC,
|
||||||
|
DESC
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LogicOperator {
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Not,
|
||||||
|
Like,
|
||||||
|
Greater,
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
NotEqual
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogicExpression
|
||||||
|
{
|
||||||
|
public object First { get; set; }
|
||||||
|
public StrategySample.LogicOperator Operator { get; set; }
|
||||||
|
public object Last { get; set; }
|
||||||
|
|
||||||
|
private StringBuilder sb = new StringBuilder();
|
||||||
|
private Func<LogicOperator, string> operatorFunc;
|
||||||
|
private Func<object, string> fieldFunc;
|
||||||
|
public string GetWhereString(Func<object, string> fieldFunc, Func<LogicOperator, string> operatorFunc) {
|
||||||
|
sb.Clear();
|
||||||
|
this.fieldFunc = fieldFunc;
|
||||||
|
this.operatorFunc = operatorFunc;
|
||||||
|
GetCondition(this);
|
||||||
|
if(sb.Length>0)
|
||||||
|
sb.Insert(0, "WHERE ");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
private void GetCondition(LogicExpression where){
|
||||||
|
ProcessExpressionTerm(where.First);
|
||||||
|
sb.Append($" {operatorFunc(where.Operator)} ");
|
||||||
|
ProcessExpressionTerm(where.Last);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessExpressionTerm(object expterm) {
|
||||||
|
if(expterm is LogicExpression newWhere) {
|
||||||
|
// recursive call
|
||||||
|
sb.Append("(");
|
||||||
|
GetCondition(newWhere);
|
||||||
|
sb.Append(")");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sb.Append(fieldFunc(expterm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IProcessor {
|
||||||
|
void SetStrategy(ISqlStrategy strategy);
|
||||||
|
|
||||||
|
List<string> Select { get; }
|
||||||
|
string From { get; }
|
||||||
|
List<(string, OrderDirection)> Orderby { get; }
|
||||||
|
LogicExpression Where { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SqlBuilderProcessor : IProcessor {
|
||||||
|
private ISqlStrategy strategy;
|
||||||
|
|
||||||
|
public SqlBuilderProcessor (ISqlStrategy strategy) {
|
||||||
|
this.strategy = strategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> Select { get; internal set; } = new List<string>();
|
||||||
|
public string From { get; set; }
|
||||||
|
|
||||||
|
public List<(string, OrderDirection)> Orderby { get; } = new List<(string, OrderDirection)>();
|
||||||
|
|
||||||
|
// public Expression Where { get; }
|
||||||
|
public LogicExpression Where { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(strategy.Select(this));
|
||||||
|
sb.Append(" ");
|
||||||
|
sb.Append(strategy.From(this));
|
||||||
|
sb.Append(" ");
|
||||||
|
sb.Append(strategy.Where(this));
|
||||||
|
sb.Append(" ");
|
||||||
|
sb.Append(strategy.OrderBy(this));
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStrategy(ISqlStrategy strategy)
|
||||||
|
{
|
||||||
|
this.strategy = strategy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SqliteStrategy : ISqlStrategy
|
||||||
|
{
|
||||||
|
public string From(IProcessor processor)
|
||||||
|
{
|
||||||
|
return $"FROM {processor.From}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OrderBy(IProcessor processor)
|
||||||
|
{
|
||||||
|
if(processor.Orderby.Any())
|
||||||
|
{
|
||||||
|
var orderby = string.Join(", ",
|
||||||
|
processor.Orderby.Select((f,d) => {
|
||||||
|
return ((OrderDirection)d == OrderDirection.ASC ?
|
||||||
|
$"{f.Item1} ASC" :
|
||||||
|
$"{f.Item1} DESC");
|
||||||
|
}).ToArray());
|
||||||
|
return $"ORDER BY {orderby}";
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Select(IProcessor processor)
|
||||||
|
{
|
||||||
|
if(processor.Select.Any())
|
||||||
|
return $"SELECT {string.Join(", ", processor.Select)}";
|
||||||
|
return "SELECT *";
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringBuilder sb = new StringBuilder();
|
||||||
|
public string Where(IProcessor processor)
|
||||||
|
{
|
||||||
|
var whereString = processor.Where.GetWhereString(f => $"{f}", l => GetOperatorSymbol(l));
|
||||||
|
if(whereString.Length>0)
|
||||||
|
return $"WHERE {whereString}";
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetOperatorSymbol(LogicOperator op)
|
||||||
|
{
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case LogicOperator.Equal:
|
||||||
|
return "=";
|
||||||
|
case LogicOperator.NotEqual:
|
||||||
|
return "<>";
|
||||||
|
case LogicOperator.Greater:
|
||||||
|
return ">";
|
||||||
|
case LogicOperator.Less:
|
||||||
|
return "<";
|
||||||
|
case LogicOperator.And:
|
||||||
|
return "AND";
|
||||||
|
case LogicOperator.Or:
|
||||||
|
return "OR";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MsSqlStrategy : ISqlStrategy
|
||||||
|
{
|
||||||
|
public string From(IProcessor processor)
|
||||||
|
{
|
||||||
|
return $"FROM [{processor.From}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetOperatorSymbol(LogicOperator op)
|
||||||
|
{
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case LogicOperator.Equal:
|
||||||
|
return "==";
|
||||||
|
case LogicOperator.NotEqual:
|
||||||
|
return "!=";
|
||||||
|
case LogicOperator.Greater:
|
||||||
|
return ">";
|
||||||
|
case LogicOperator.Less:
|
||||||
|
return "<";
|
||||||
|
case LogicOperator.And:
|
||||||
|
return "And";
|
||||||
|
case LogicOperator.Or:
|
||||||
|
return "Or";
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OrderBy(IProcessor processor)
|
||||||
|
{
|
||||||
|
if(processor.Orderby.Any())
|
||||||
|
{
|
||||||
|
var orderby = string.Join(", ",
|
||||||
|
processor.Orderby.Select((f,d) => {
|
||||||
|
return ((OrderDirection)d == OrderDirection.ASC ?
|
||||||
|
$"[{f.Item1}] ASC" :
|
||||||
|
$"[{f.Item1}] DESC");
|
||||||
|
}).ToArray());
|
||||||
|
return $"ORDER BY {orderby}";
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Select(IProcessor processor)
|
||||||
|
{
|
||||||
|
if(processor.Select.Any())
|
||||||
|
return $"SELECT {string.Join(", ", processor.Select.Select(f => $"[{f}]"))}";
|
||||||
|
return "SELECT *";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Where(IProcessor processor)
|
||||||
|
{
|
||||||
|
var whereString = processor.Where.GetWhereString(f => $"[{f}]", l => GetOperatorSymbol(l));
|
||||||
|
if(whereString.Length>0)
|
||||||
|
return $"WHERE {whereString}";
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user