我必须实现一个审计系统,在这个系统中,用户必须提供执行某个操作所需的理由。当他提供理由时,他可以自由地表演一段时间。操作的每一次执行都需要在某个地方进行记录。
我使用延拓传递方式实现了它,它允许我干净地处理原子权限检查和操作日志记录。
public class AuditLogger
{
private readonly TimeSpan permissionDuration;
private readonly IAuditDatabase auditDatabase;
private DateTime permissionExpiry = DateTime.MinValue;
private string accessReason;
public AuditLogger(TimeSpan permissionDuration, IAuditDatabase auditDatabase)
{
this.permissionDuration = permissionDuration;
this.auditDatabase = auditDatabase;
}
private bool CheckPermission()
{
return DateTime.UTCNow < permissionExpiry;
}
public void SetAccessReason(string reason)
{
reason = reason;
permissionExpiry = DateTime.UTCNow.Add(permissionDuration);
}
public void LogAccessAndExecuteOperation(Action operation, Action onPermissionExpired, Action<Exception> onError)
{
if(CheckPermission())
onPermissionExpired();
try
{
auditDatabase.Log(reason);
operation();
}
catch(Exception exception)
{
onError(exception);
}
}
}你觉得那个怎么样?
这里是一些客户端代码,以显示应该如何使用它。
public static void Main(string[] args)
{
var auditLogger = new AuditLogger(TimeSpan.FromMinutes(15), new AuditingDatabase);
var reason = args[0]; // Let's assume the user tells us what he needs to do at startup
auditLogger.SetAccessReason(reason);
// Now the user keeps doing lots of things
while(1)
{
auditLogger.LogAccessAndExecuteOperation(
() => { /* doing nothing here */ Thread.Sleep(1000); },
() => {
Console.WriteLine("Time's up. Can you please tell us again what you need to do?");
reason = Console.ReadLine();
auditLogger.SetAccessReason(reason);
},
exeption => Console.WriteLine(exception)
);
}
}发布于 2014-10-03 23:18:06
不幸的是,该类违反了单一责任原则,因为它必须处理日志记录和到期的访问。
您可以在这里使用装饰图案并将授权和日志记录拆分为不同的类,如下所示:
public interface IAccessWidget
{
string AccessReason { get; }
void SetAccessReason(string reason);
void ExecuteOperation(Action operation, Action onPermissionExpired, Action<Exception> onError);
}
public class AccessWidget
{
private readonly TimeSpan _permissionDuration;
private DateTime _permissionExpiry = DateTime.MinValue;
public string AccessReason { get; private set; }
public AccessWidget(TimeSpan permissionDuration)
{
_permissionDuration = permissionDuration;
}
private bool CheckPermission()
{
return DateTime.UtcNow < _permissionExpiry;
}
public void SetAccessReason(string reason)
{
AccessReason = reason;
_permissionExpiry = DateTime.UtcNow.Add(_permissionDuration);
}
public void ExecuteOperation(Action operation, Action onPermissionExpired, Action<Exception> onError)
{
if(CheckPermission())
onPermissionExpired();
try
{
operation();
}
catch(Exception exception)
{
onError(exception);
}
}
}
public class LoggingAccessWidget : IAccessWidget
{
private readonly IAuditDatabase _auditDatabase;
private readonly IAccessWidget _widget;
public string AccessReason { get { return _widget.AccessReason; } }
public LoggingAccessWidget(IAccessWidget widget, IAuditDatabase auditDatabase)
{
_widget = widget;
_auditDatabase = auditDatabase;
}
public void SetAccessReason(string reason)
{
_widget.SetAccessReason(reason);
}
public void ExecuteOperation(Action operation, Action onPermissionExpired, Action<Exception> onError)
{
_auditDatabase.Log(_widget.AccessReason);
_widget.ExecuteOperation(operation, onPermissionExpired, onError);
}
}https://codereview.stackexchange.com/questions/64674
复制相似问题