-
OOP Design Pattern - Behavioral Pattern 1프로그래밍 언어 2024. 10. 14. 22:28
Chain of Responsibility
Chain-of-Responsibility Pattern
- A behavioral design pattern consisting of a source of command objects and a series of processing objects
- Each processing object contains logic that defines the types of command objects that it can handle
- The rest are passed to the next processing object in the chain
- A mechanism exists for adding new processing objects to the end of this chain
- Variation : act as dispatchers, capable of sending commands out in a variety of directions, forming a tree of responsibility
- Can occur recursively, with processing objects calling higher-up processing objects
- Recursion continues until the command is prcessed, or the entire tree has been explored
Overview
- Solves problem like:
- Coupling the sender of a request to its receiver should be avoided
- It should be possible that more than one receiver can handle a request
- Describes how to solve such problems:
- Define a chain of receiver objects having the responsiblity, depending on run-time conditions, to either handle a request or forward it to the next receiver on the chain (if any)
Example
[Flags] public enum LogLevel { None = 0, // 0 Info = 1, // 1 Debug = 2, // 10 Warning = 4, // 100 Error = 8, // 1000 FunctionalMessage = 16, // 10000 FunctionalError = 32, // 100000 All = 63 // 111111 } // Abstract Handler in chain of responsibility pattern. public abstract class Logger { protected LogLevel logMask; protected Logger next; // The next handler in the chain public Logger(LogLevel mask) { this.logMask = mask; } // Sets the next logger to make a list / chain of handlers. public Logger SetNext(Logger nextLogger) { Logger lastLogger = this; while (lastLogger.next != null) { lastLogger = lastLogger.next; } lastLogger.next = nextLogger; return this; } public void Message(string msg, LogLevel severity) { // Tru only if any of the logMask bits are set in severity if ((severity & logMask) != 0) WriteMessage(msg); if (next != null) next.Message(msg, severity); } protected abstract void WriteMessage(string msg); } public class ConsoleLogger : Logger { public ConsoleLogger(LogLevel mask) : base(mask) { } protected override void WriteMessage(string msg) { Console.WriteLine("Writing to console : " + msg); } } public class EmailLogger : Logger { public EmailLogger(LogLevel mask) : base(mask) { } protected override void WriteMessage(string msg) { // Placeholder for mail send logic, usually the email configurations are saved in config file. Console.WriteLine("Sending via email : " + msg); } } public class FileLogger : Logger { public FileLogger(LogLevel mask) : base(mask) { } protected override void WriteMessage(string msg) { Console.WriteLine("Writing to log file : " + msg); } } public class Program { public static void Main(string[] args) { // Build the chain of responsibility Logger logger = new ConsoleLogger(LogLevel.All) .SetNext(new EmailLogger(LogLevel.FunctionalMessage | LogLevel.FunctionalError)) .SetNext(new FileLogger(LogLevel.Warning | LogLevel.Error)); // Handled by ConsoleLogger since the console has a loglevel of all logger.Message("Entering function ProcessOrder().", LogLevel.Debug); logger.Message("Order record retrieved.", LogLevel.Info); // Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error logger.Message("Customer Address details missing in Branch DataBase.", LogLevel.Warning); logger.Message("Customer Address details missing in Organization DataBase.", LogLevel.Error); // Handled by ConsoleLogger and EmailLogger as it implements functional error logger.Message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FunctionalError); // Handled by ConsoleLogger and EmailLogger logger.Message("Order Dispatched.", LogLevel.FunctionalMessage); } }
Command
Command Pattern
- A behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time
- The information includes the method name, the object that owns the method and values for the method parameters
- Command
- Knows about receiver and invokes a method of the receiver
- Values for parameters of the receiver method are stored in the command
- Receiver
- The object to execute methods
- Stored in the command object by aggregation
- Works when the execute() method in command is called
- Invoker
- Knows how to execute a command, and optionally does bookkeeping about the command execution
- Does not know anything about a concrete command
- Knows only about the command interface
- Client : decides which command to execute at which points
Overview
- Solves problem like:
- Coupling the invoker of a request to a particular request should be avoided
- It should be possible to configure an object (that invokes a request) with a request
- Describes how to solve such problem:
- Define separate (command) objects that encapsulate a request
- A class delegates a request to a command object instead of implementing a particular request directly
Example
public interface Command { public void Execute(); } public class CommandFire : Command { public void Execute() { Fire(); } public void Fire() { Console.WriteLine("Fire"); } } public class CommandJump : Command { public void Execute() { Jump(); } public void Jump() { Console.WriteLine("Jump"); } } public class CommandRoll : Command { public void Execute() { Roll(); } public void Roll() { Console.WriteLine("Roll"); } }
Interpreter
Interpreter Pattern
- Specifies how to evaluate sentences in a language
- Have a class for each symbol in a specialized computer language
Overview
- Solves problem like:
- A grammar for a simple language should be defined so that sentences in the language can be interpreted
- Describes how to solve such problems:
- Define a grammar for a simple language by defining a Expression class hierarchy and implementing an interpret() operation
- Represent a sentence in the language by an abstract syntax tree (AST) made up of Expression instances
- Interpret a sentence by calling interpret() on the AST
Example
using System; using System.Collection.Generic; namespace OOP; public class Context { public Stack<string> Result = new Stack<string>(); } public interface IExpression { public void Interpret(Context context); } public abstract class OperatorExpression : IExpression { public IExpression Left { set; private get; } public IExpression Right { set; private get; } public void Interpret(Context context) { Left.Interpret(context); string leftValue = context.Result.Pop(); Right.Interpret(context); string rightValue = context.Result.Pop(); DoInterpret(context, leftValue, rightValue); } protected abstract void DoInterpret(Context context, string leftValue, string rightValue); } public class EqualsExpression : OperatorExpression { protected override void DoInterpret(Context context, string leftValue, string rightValue) { context.Result.Push(leftValue == rightValue ? "true" : "false"); } } public class OrExpression : OperatorExpression { protected override void DoInterpret(Context context, string leftValue, string rightValue) { context.Result.Push(leftValue == "true" || rightValue == "true" ? "true" : "false"); } } public class MyExpression : IExpression { public string Value { private get; set; } public void Interpret(Context context) { context.Result.Push(Value); } } public class Program { public static void Main() { var context = new Context(); var input = new MyExpression(); var expression = new OrExpression { Left = new EqualsExpression { Left = input, Right = new MyExpression { Value = "4" } }, Right = new EqualsExpression { Left = input, Right = new MyExpression { Value = "four" } } }; input.Value = "four"; expression.Interpret(context); // Output : "true" Console.WriteLine(context.Result.Pop()); input.Value = "44"; expression.Interpret(context); // Output : "false" Console.WriteLine(context.Result.Pop()); } }
'프로그래밍 언어' 카테고리의 다른 글
[C#] Public Field vs Auto-Implemented Property (0) 2024.04.06 OOP Design Pattern - Structural Pattern (0) 2024.01.18 OOP Design Pattern - Creational Pattern (0) 2024.01.12 [C++] 이동 의미론 Move Semantics (0) 2023.11.20 입실론 테스트 (0) 2023.11.20