做为软件开发工程师,肯定都了解23种设计模式,关于设计模式是否有用常见的也有几种论调,一是这玩意用处不大。二是设计模式很重要,而且要提到至关重要的那个级别。三是中间路线,设计模式有用,但是不能说至关重要。
个人觉得设计模式的重要性跟项目规模/复杂度、技术路线、人员开发水平都有很大关系。通常小的项目可能没有必要强调设计模式,可能有人会讲这个为了后续的维护怎么样,也要进行好好设计,但是通常情况是小项目也不会分配高手,可能监管也不会有太大力度。但是如果项目复杂或者我们要开发长期更新的组件,那通常要精雕细琢。
设计模式是软件开发人员在开发过程中面临的常见问题的一组最佳实践和解决方案。这些模式通常是可重用的,并且可以应用于不同的项目。
设计模式不是语言功能或库,而是一种组织代码以使其更易于维护、可扩展和可重用的方式。它们通常分为三种类型:创建模式、结构模式和行为模式。
创建模式处理对象创建机制,尝试以适合情况的方式创建对象。结构模式处理对象组成,行为模式处理对象之间的通信。
一、创建设计模式
创建设计模式用于以适合特定情况的方式创建对象。.NET 开发中最常用的创建设计模式包括:
1. 单例模式
单例模式用于确保类只有一个实例,并提供对该实例的全局访问点。在 .NET 中,单一实例模式是使用私有构造函数和保存类的单个实例的静态字段实现的。当您希望确保只创建类的一个实例,并且希望提供对该实例的全局访问点时,此模式非常有用。
public sealed class Singleton
{
private static Singleton instance = null;
private static readonly object lockObject = new object();
private Singleton() {}
public static Singleton Instance
{
get
{
lock(lockObject)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
}
2. 工厂模式
工厂模式用于创建对象,而不向客户端公开创建逻辑。在 .NET 中,工厂模式是使用基于一组参数创建对象的类或方法实现的。当您想要基于一组特定条件创建对象,并且希望对客户端隐藏创建逻辑时,此模式非常有用。
public interface IAnimalFactory
{
IAnimal Create();
}
public class DogFactory : IAnimalFactory
{
public IAnimal Create()
{
return new Dog();
}
}
public class CatFactory : IAnimalFactory
{
public IAnimal Create()
{
return new Cat();
}
}
public interface IAnimal
{
string Speak();
}
public class Dog : IAnimal
{
public string Speak()
{
return "Woof!";
}
}
public class Cat : IAnimal
{
public string Speak()
{
return "Meow!";
}
}
3. 生成器模式
生成器模式用于将复杂对象的构造与其表示形式分开。在 .NET 中,生成器模式是使用单独的类或方法逐步构造对象的实现的。如果要创建具有许多组件的复杂对象,并且希望将构造逻辑与表示形式分开,则此模式非常有用。
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
public class PersonBuilder
{
private readonly Person person;
public PersonBuilder()
{
person = new Person();
}
public PersonBuilder WithFirstName(string firstName)
{
person.FirstName = firstName;
return this;
}
public PersonBuilder WithLastName(string lastName)
{
person.LastName = lastName;
return this;
}
public PersonBuilder WithAge(int age)
{
person.Age = age;
return this;
}
public PersonBuilder WithAddress(string address)
{
person.Address = address;
return this;
}
public Person Build()
{
return person;
}
}
4. 依赖注入模式
依赖关系注入模式是一种创建模式,它提供了一种创建对象的方法,而无需知道它们是如何构造的详细信息。当您需要创建具有复杂依赖项或难以实例化的对象时,这很有用。
public interface IDataAccessLayer
{
void SaveData(string data);
}
public class SqlDataAccessLayer : IDataAccessLayer
{
public void SaveData(string data)
{
// Implementation of saving data in SQL Server
}
}
public class BusinessLogicLayer
{
private readonly IDataAccessLayer _dataAccessLayer;
public BusinessLogicLayer(IDataAccessLayer dataAccessLayer)
{
_dataAccessLayer = dataAccessLayer;
}
public void SaveData(string data)
{
_dataAccessLayer.SaveData(data);
}
}
二、结构设计模式
结构设计模式用于定义对象之间的关系以及如何组合它们以形成更大的结构。.NET 开发中最常用的结构设计模式包括:
1. 适配器模式
适配器模式用于将类的接口转换为客户端所需的另一个接口。在 .NET 中,适配器模式是使用充当两个不兼容接口之间的桥梁的单独类实现的。如果要使用与现有代码库不兼容的类,并且希望转换其接口以使其兼容,则此模式非常有用。
public interface ITarget
{
void Request();
}
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Specific request");
}
}
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public void Request()
{
_adaptee.SpecificRequest();
}
}
2. 装饰器图案
装饰器模式用于动态地向对象添加功能。在 .NET 中,装饰器模式是使用包装原始对象并提供附加功能的单独类实现的。当您想要在不更改对象接口的情况下向对象添加功能时,此模式非常有用。
public interface ICoffee
{
string GetDescription();
double GetCost();
}
public class SimpleCoffee : ICoffee
{
public string GetDescription()
{
return "Simple Coffee";
}
public double GetCost()
{
return 1.0;
}
}
public class CoffeeWithMilk : ICoffee
{
private readonly ICoffee _coffee;
public CoffeeWithMilk(ICoffee coffee)
{
_coffee = coffee;
}
public string GetDescription()
{
return _coffee.GetDescription() + ", with milk";
}
public double GetCost()
{
return _coffee.GetCost() + 0.5;
}
}
3. 外观模式
外观模式用于为复杂系统提供简单的接口。在 .NET 中,外观模式是使用单独的类实现的,该类为现有系统提供简化的接口。当您想要简化与复杂系统的交互,并且希望对客户端隐藏其复杂性时,此模式非常有用。
// Complex subsystem with many parts
public class Subsystem1
{
public void Operation1()
{
Console.WriteLine("Subsystem1: Operation1");
}
public void Operation2()
{
Console.WriteLine("Subsystem1: Operation2");
}
}
public class Subsystem2
{
public void Operation3()
{
Console.WriteLine("Subsystem2: Operation3");
}
public void Operation4()
{
Console.WriteLine("Subsystem2: Operation4");
}
}
public class Subsystem3
{
public void Operation5()
{
Console.WriteLine("Subsystem3: Operation5");
}
public void Operation6()
{
Console.WriteLine("Subsystem3: Operation6");
}
}
// Facade that simplifies the interface to the subsystem
public class Facade
{
private readonly Subsystem1 _subsystem1;
private readonly Subsystem2 _subsystem2;
private readonly Subsystem3 _subsystem3;
public Facade()
{
_subsystem1 = new Subsystem1();
_subsystem2 = new Subsystem2();
_subsystem3 = new Subsystem3();
}
public void Operation()
{
_subsystem1.Operation1();
_subsystem2.Operation4();
_subsystem3.Operation6();
}
}
4. 桥模式
Bridge 模式用于将抽象与其实现分离,允许它们独立变化。它提供了一种创建具有不同实现的相关类系列的方法。当我们想要互换使用的类的多个变体时,这种模式特别有用。
public interface IImplementor
{
void OperationImpl();
}
public class ConcreteImplementorA : IImplementor
{
public void OperationImpl()
{
Console.WriteLine("Concrete Implementor A");
}
}
public class ConcreteImplementorB : IImplementor
{
public void OperationImpl()
{
Console.WriteLine("Concrete Implementor B");
}
}
public abstract class Abstraction
{
protected IImplementor _implementor;
public Abstraction(IImplementor implementor)
{
_implementor = implementor;
}
public virtual void Operation()
{
_implementor.OperationImpl();
}
}
public class RefinedAbstraction : Abstraction
{
public RefinedAbstraction(IImplementor implementor) : base(implementor)
{
}
public override void Operation()
{
_implementor.OperationImpl();
}
}
三、行为设计模式
1. 观察者模式
观察者模式是一种行为设计模式,它允许称为主体的对象在其状态更改时通知观察者列表。然后自动通知和更新观察者。这种模式的一个典型例子是新闻机构在新文章发布时通知其订阅者。
public interface IObserver
{
void Update();
}
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
public class ConcreteSubject : ISubject
{
private List<IObserver> _observers = new List<IObserver>();
private string _state;
public string State
{
get { return _state; }
set
{
_state = value;
Notify();
}
}
public void Attach(IObserver observer)
{
_observers.Add(observer);
}
public void Detach(IObserver observer)
{
_observers.Remove(observer);
}
public void Notify()
{
foreach (IObserver observer in _observers)
{
observer.Update();
}
}
}
public class ConcreteObserver : IObserver
{
private string _name;
private string _observerState;
private ConcreteSubject _subject;
public ConcreteObserver(ConcreteSubject subject, string name)
{
_subject = subject;
_name = name;
}
public void Update()
{
_observerState = _subject.State;
Console.WriteLine($"Observer {_name}'s new state is {_observerState}");
}
}
public static void Main()
{
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observerA = new ConcreteObserver(subject, "A");
ConcreteObserver observerB = new ConcreteObserver(subject, "B");
ConcreteObserver observerC = new ConcreteObserver(subject, "C");
subject.Attach(observerA);
subject.Attach(observerB);
subject.Attach(observerC);
subject.State = "New State";
}
2. 命令模式
命令模式是一种行为设计模式,它将请求封装为对象,从而允许使用不同的请求、队列和日志请求对客户端进行参数化,并支持可撤消的操作。这种模式的一个典型例子是电视的遥控器,其中每个按钮按下对应于不同的命令。
public interface ICommand
{
void Execute();
}
public class Receiver
{
public void Action()
{
Console.WriteLine("Receiver does some action");
}
}
public class ConcreteCommand : ICommand
{
private Receiver _receiver;
public ConcreteCommand(Receiver receiver)
{
_receiver = receiver;
}
public void Execute()
{
_receiver.Action();
}
}
public class Invoker
{
private ICommand _command;
public void SetCommand(ICommand command)
{
_command = command;
}
public void ExecuteCommand()
{
_command.Execute();
}
}
public static void Main()
{
Invoker invoker = new Invoker();
Receiver receiver = new Receiver();
ConcreteCommand command = new ConcreteCommand(receiver);
invoker.SetCommand(command);
invoker.ExecuteCommand();
}
3. 策略模式
策略模式是一种行为设计模式,允许客户端在运行时从一系列算法中进行选择。当有多种算法可用于解决问题,并且算法的选择取决于上下文时,此模式非常有用。此模式的一个典型示例是可以根据输入数据的大小选择的排序算法。
public interface IStrategy
{
void AlgorithmInterface();
}
public class ConcreteStrategyA : IStrategy
{
public void AlgorithmInterface()
{
Console.WriteLine("ConcreteStrategyA.AlgorithmInterface()");
}
}
public class ConcreteStrategyB : IStrategy
{
public void AlgorithmInterface()
{
Console.WriteLine("ConcreteStrategyB.AlgorithmInterface()");
}
}
public class Context
{
private IStrategy _strategy;
public Context(IStrategy strategy)
{
_strategy = strategy;
}
public void ContextInterface()
{
_strategy.AlgorithmInterface();
}
}
public static void Main()
{
Context context;
context = new Context(new ConcreteStrategyA());
context.ContextInterface();
context = new Context(new ConcreteStrategyB());
context.ContextInterface();
}
四、小结
在 .NET 开发中了解和使用设计模式可以大大提高代码的质量、可伸缩性和可维护性。在本文中,我们讨论了 .NET 开发中最常用的设计模式,但此处未涉及更多模式。通过将这些模式合并到代码中,您可以编写易于维护、扩展和随时间推移修改的高质量软件。