mirror of
https://github.com/farcasclaudiu/design_pattens.git
synced 2026-06-22 05:01:30 +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.observer;
|
||||
using design_patterns.behavioral.state;
|
||||
using design_patterns.behavioral.strategy;
|
||||
|
||||
namespace design_patterns
|
||||
{
|
||||
@@ -55,7 +56,8 @@ namespace design_patterns
|
||||
// await MediatorSample.Run();
|
||||
// await MementoSample.Run();
|
||||
// await ObserverSample.Run();
|
||||
await StateSample.Run();
|
||||
// await StateSample.Run();
|
||||
await StrategySample.Run();
|
||||
}
|
||||
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