C# 介绍;“强制性”;接口实现者的方法
当前的实现与一个简单的策略设计模式非常一致。需要执行多个步骤,这些步骤将由以下接口调用:C# 介绍;“强制性”;接口实现者的方法,c#,oop,design-patterns,interface,C#,Oop,Design Patterns,Interface,当前的实现与一个简单的策略设计模式非常一致。需要执行多个步骤,这些步骤将由以下接口调用: public interface ICommandStep { void Execute(CommandParameters cParams); string StepName { get; } } 示例实现者: public class Step1 : ICommandStep { public string StepName => "Initial Step";
public interface ICommandStep
{
void Execute(CommandParameters cParams);
string StepName { get; }
}
示例实现者:
public class Step1 : ICommandStep {
public string StepName => "Initial Step";
public void Execute(CommandParameters cParams) {
// instructions
}
}
到目前为止,有许多不同的类实现了这个接口,我想确保它们都有一个执行前和执行后的步骤。例如,日志状态、参数、步骤名开始和结束
我如何介绍一种方法,使用公共(可重写)逻辑使受保护的virtual void PreExecute
和受保护的virtual void PostExecute
方法,并确保始终按以下顺序调用该方法:
1. PreExecute
2. Execute
3. PostExecute
最好不改变实现器类中的Execute方法
引入抽象类是可能的。您可以按照需要的顺序声明基类并定义可重写的方法:
public interface ICommandStep
{
void Execute(CommandParameters cParams);
string StepName { get; }
}
public abstract class CommandBase : ICommandStep
{
public void Execute(CommandParameters cParams)
{
PreExecute();
ExecuteInternal(cParams);
PostExecute();
}
protected virtual void PostExecute()
{
}
protected virtual void ExecuteInternal(CommandParameters cParams)
{
}
protected virtual void PreExecute()
{
}
public abstract string StepName { get; }
}
public class Step1 : CommandBase
{
public override string StepName => "Initial Step";
protected override void ExecuteInternal(object cParams)
{
// instructions
}
}
向接口添加新方法必然意味着破坏现有的实现。如果实现是可选的,那么应该使用
抽象
类而不是接口
另一种方法是添加新接口并在扩展方法中添加运行时类型检查,如下所示:
public interface ICommandStep
{
void Execute(CommandParameters cParams);
string StepName { get; }
}
public interface ICommandStep2 : ICommandStep
{
void PreExecute()
void PostExecute()
}
public static class Extensions
{
public static void Execute2(this ICommandStep step, CommandParameters cParams)
{
if( step is ICommandStep2 step2 )
{
step2.PreExecute();
step2.Execute( cParams );
step2.PostExecute();
}
else
{
step2.Execute( cParams );
}
}
}
用法:
ICommandStep[] steps = ...
foreach( ICommandStep step in steps )
{
step.Execute2( cmdParams );
}
我可以想出两种解决方案:
using System;
namespace ConsoleApplication6
{
/// <summary>
/// This is the component in Decorator Pattern
/// </summary>
public interface ICommandStep
{
void Execute(String cParams);
string StepName { get; }
}
/// <summary>
/// This is the concrete component in Decorator Pattern
/// </summary>
public class ConcreteStep1 : ICommandStep
{
public string StepName
{
get
{
return "1";
}
}
public void Execute(string cParams)
{
Console.WriteLine($"STEP {StepName}: EXECUTE");
}
}
/// <summary>
/// This is the decorator in Decorator Pattern
/// </summary>
public abstract class StepDecorator : ICommandStep
{
protected ICommandStep _commandStep;
public abstract string StepName
{
get;
}
public StepDecorator(ICommandStep commandStep)
{
this._commandStep = commandStep;
}
public abstract void Execute(string cParams);
}
/// <summary>
/// This is the concrete decorator in Decorator Pattern
/// </summary>
public class ConcreteStepDecorator : StepDecorator
{
public ConcreteStepDecorator(ICommandStep commandStep) : base(commandStep) { }
public override string StepName
{
get
{
return _commandStep.StepName;
}
}
public override void Execute(string cParams)
{
// You can do whatever you want before / after execution of command
Console.WriteLine($"STEP {_commandStep.StepName}: PRE EXECUTE");
_commandStep.Execute(cParams);
Console.WriteLine($"STEP {_commandStep.StepName}: POST EXECUTE");
}
}
/// <summary>
/// This is a Simple Factory. You encapsulate here creation of ICommandStep, so that it will always be decorated
/// </summary>
public class SimpleStepFactory
{
public ICommandStep createStep()
{
return new ConcreteStepDecorator(new ConcreteStep1());
}
}
class Program
{
static void Main(string[] args)
{
var step = new SimpleStepFactory().createStep();
step.Execute("params");
Console.ReadLine();
}
}
}
使用系统;
命名空间控制台应用程序6
{
///
///这是Decorator模式中的组件
///
公共接口ICommandStep
{
无效执行(字符串cparam);
字符串步骤名{get;}
}
///
///这是Decorator模式中的具体组件
///
公共类具体步骤1:ICommandStep
{
公共字符串步骤名
{
得到
{
返回“1”;
}
}
public void Execute(字符串cParams)
{
WriteLine($“步骤{StepName}:EXECUTE”);
}
}
///
///这是decorator模式中的decorator
///
公共抽象类StepDecorator:ICommandStep
{
受保护的ICommandStep\u commandStep;
公共抽象字符串步骤名
{
得到;
}
公共步骤装饰器(ICommandStep命令步骤)
{
这个._commandStep=commandStep;
}
公共抽象void Execute(字符串cparam);
}
///
///这是decorator模式中的具体decorator
///
公共类ConcreteStepDecorator:StepDecorator
{
公共ConcreteStepDecorator(ICommandStepCommandStep):基(commandStep){}
公共重写字符串StepName
{
得到
{
返回_commandStep.StepName;
}
}
公共重写无效执行(字符串CPARAM)
{
//在执行命令之前/之后,您可以做任何您想做的事情
WriteLine($“步骤{u commandStep.StepName}:预执行”);
_commandStep.Execute(cParams);
WriteLine($“步骤{{u commandStep.StepName}:POST-EXECUTE”);
}
}
///
///这是一个简单的工厂。您在这里封装了ICommandStep的创建,因此它将始终被装饰
///
公共类简单工厂
{
公共ICommandStep createStep()
{
返回新的ConcreteStepDecorator(新的ConcreteStep1());
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var step=new SimpleStepFactory().createStep();
步骤。执行(“参数”);
Console.ReadLine();
}
}
}
此解决方案有两个优点:
- 您可以使用许多decorator来包装步骤,也就是说,您可以在decorator中包装显示其名称的步骤,并在另一个显示参数的decorator中包装这两个步骤
- 您不必修改您的步骤,因为所有额外的工作都是由装饰人员处理的