问题描述:当一个函数中处理一个特性时,如果特性包含了多个职责,则这个函数也包含了多个职责。只有通读整个函数的逻辑结构后才能知道这个函数具体实现什么功能。
单一职责原则要求一个类应该只有一个变更理由,函数也是如此。
重构清晰度:将包含多职责的函数拆分成多个更小的函数,每个函数只处理其中一条职责。这样重构之后增加了代码的清晰度,但是代码的适应性没有得到任何提高。需要修改其中一个函数的方法时,需要修改方法内容,违背了开闭原则。
重构抽象:根据上面拆分出来的多个函数,设计实现单一职责的接口以及实现类。在调用处引用创建的接口来执行对应的工作。接口实现类则仅有单一职责变更时才会进行改变。
单一职责原则和修饰器模式
修饰器模式(Decorator Pattern, DP)能够很好的确保每个类只有单一职责。一般情况下,完成很多事情的类不能轻易的将职责划分到其他类型中,因为很多职责看起来是相互关联的。
修饰器模式的前置条件:每个修饰器类实现一个接口且能同时接受一个或多个同一个接口实例作为构造函数的输入参数。这样的好处在于可以给已经实现了某个特定接口的类添加功能,而且修饰器同时也是所需接口的一个实现,并且对用户不可见。
public interface Icomponent
{
void Something();
}
///
public class ConcreteComponent:Icomponent
{
public void Something(){ // };
}
public class DecoratorComponent:Icomponent
{
public DecoratorComponent(Icomponent decoratedComponent)
{
this.decoratedComponent = decoratedComponent;
}
public void Something()
{
// Do Other Things
decoratedComponent.Something();
};
}
}
1、 复合模式(Composite Pattern):让某个接口的一组实例看作该接口的一个实例。客户端只需要接受接口的一个实例,在无需任何改变的情况下就能隐式的使用该接口的一组实例。
public interface IComponent
{
void Something();
}
public class Leaf : IComponent
{
public void Something()
{
}
}
public class CompositeComponent : IComponent
{
List<IComponent> children = null;
public CompositeComponent()
{
children = new List<IComponent>();
}
public void Something()
{
foreach (IComponent child in children)
{
child.Something();
}
}
public void AddComponent(IComponent component)
{
children.Add(component);
}
public void RemoveComponent(IComponent component)
{
children.Remove(component);
}
}
{
static void Main(string[] args)
{
var composite = new CompositeComponent();
composite.AddComponent(new Leaf());
composite.AddComponent(new Leaf());
composite.AddComponent(new Leaf());
component = composite;
component.Something();
}
static IComponent component;
}
多用于显示树结构。
2、谓词修饰器(Predicate Decorator):能够很好的消除客户端代码中的条件执行语句。将条件判断语句提出一个接口,将接口放到谓词修饰器中进行判断。
3、分支修饰器:在谓词修饰器基础上进行修改,传入三个参数,当谓词为true 或false时分别执行两个不同的接口实例操作。
4、延迟修饰器:延迟修饰器允许客户端提供摸个接口的引用,但是直到第一次使用他时才进行实例化。同床客户端直到看到传入参数类型为Lazy<T>类型时才会察觉到延迟实例的存在。但是不应该让他们知道延迟实例存在的细节信息。
// 客户端可以看到具体的延迟接口,适应性差,不能接收非延迟性IComponent接口
public class ComponentClient
{
private Lazy<IComponent> component;
public ComponentClient(Lazy<IComponent> component)
{
this.component = component;
}
public void Runing()
{
component.Value.Something();
}
}
// 使用延迟适配器,客户端可以兼容延迟与非延迟接口
public class LazyComponent : IComponent
{
private Lazy<IComponent> component;
public LazyComponent(Lazy<IComponent> component)
{
this.component = component;
}
public void Runing()
{
component.Value.Something();
}
}
public class ComponentClient
{
private IComponent component;
public ComponentClient(IComponent component)
{
this.component = component;
}
public void Runing()
{
component.Something();
}
}
5、日志记录修饰器:
6、性能修饰器:
7、异步修饰器:
8、修饰属性和事件
用策略模式替代Switch语句:
任何使用Switch语句的场合,都可以通过策略模式将复杂性委托给依赖的接口以简化客户端代码。策略模式能够提供更好的适应变更的能力。