C# 软件设计模式-行为型模式【11种】

行为型模式主要关注对象之间的交互和职责分配,旨在通过定义对象之间的通信方式和行为协作来实现特定的功能。有助于提高系统的灵活性、可维护性和可扩展性,使系统更加易于理解和管理。它们在构建复杂的软件系统中发挥着重要作用,帮助开发者更好地组织和协调对象之间的行为和交互。

一、策略模式:定义一系列算法,并将它们封装起来,使它们可以相互替换。

策略模式是一种行为型设计模式,其核心在于将算法的定义、使用和切换进行有效的分离。通过这种模式,系统能够根据不同的情境和需求,灵活地选择和应用相应的策略。

在实际的编程实践中,策略模式展现出诸多显著优势。它极大地增强了系统的可扩展性和可维护性。当需要添加新的策略或修改现有策略时,无需对使用策略的主体代码进行大规模的改动,只需专注于策略本身的实现和调整。

这种模式促进了代码的模块化和封装性。不同的策略可以被清晰地封装在各自的类中,彼此独立且互不干扰。这不仅提高了代码的可读性和可理解性,也为后续的开发和维护提供了便利。

在复杂的业务场景中,策略模式能够帮助我们更好地应对多样化的需求和变化。例如,在一个计费系统中,可以根据不同的客户类型或交易场景选择不同的计费策略;在游戏中,可以根据玩家的行为或游戏状态切换不同的游戏策略。

然而,运用策略模式也并非毫无挑战。在设计和实现策略时,需要仔细考虑策略之间的关系和边界,以确保系统的稳定性和正确性。同时,对于策略的管理和组织也需要合理规划,以便于在系统运行过程中能够高效地选择和切换策略。
以下是一个在 C# 中实现策略模式的简单示例:

首先定义一个策略接口:

interface IStrategy
{
    void Execute();
}

然后创建具体的策略类:

class StrategyA : IStrategy
{
    public void Execute()
    {
        Console.WriteLine("执行策略 A");
    }
}

class StrategyB : IStrategy
{
    public void Execute()
    {
        Console.WriteLine("执行策略 B");
    }
}

再创建一个使用策略的上下文类:

class Context
{
    private IStrategy strategy;

    public void SetStrategy(IStrategy strategy)
    {
        this.strategy = strategy;
    }

    public void DoSomething()
    {
        strategy.Execute();
    }
}

在使用时,可以这样操作:

class Program
{
    static void Main()
    {
        Context context = new Context();

        context.SetStrategy(new StrategyA());
        context.DoSomething();

        context.SetStrategy(new StrategyB());
        context.DoSomething();
    }
}

使用策略模式时需要注意以下几点:

  1. 明确策略边界:确保每个策略的功能定义清晰,避免策略之间的职责模糊不清。

  2. 策略的独立性:策略类之间应保持相对独立,减少相互依赖和干扰。

  3. 策略的可维护性:随着系统的发展,可能会有新的策略加入或现有策略的修改,要确保这种变化易于进行且不影响其他部分。

  4. 上下文与策略的解耦:上下文类不应过度依赖于具体的策略实现,以便灵活切换策略。

  5. 策略的数量控制:避免无节制地增加策略数量,以免导致系统过于复杂和难以管理。

  6. 策略的测试:对每个策略进行充分的测试,以保证其正确性和稳定性。

  7. 策略的命名规范:使用清晰、有意义的命名来区分不同的策略,提高代码的可读性。

  8. 性能考虑:在某些对性能要求较高的场景下,要评估策略模式的使用是否会带来额外的开销。

  9. 与其他模式的配合:可以结合其他设计模式来更好地构建系统架构,发挥各自的优势。

  10. 文档说明:对策略模式的使用和各个策略的功能进行详细的文档说明,方便其他开发人员理解和维护。

总之,策略模式是软件开发中一种非常有价值的设计模式。它为我们构建灵活、可扩展且易于维护的系统提供了有力的支持和保障。正确理解和熟练运用这一模式,对于提升软件质量和开发效率具有不可忽视的意义。

二、模板方法模式:定义一个操作中的算法框架,而将一些步骤延迟到子类中实现。

模板方法模式定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。它允许子类在不改变算法结构的情况下,重新定义算法中的某些特定步骤。

这种模式的核心在于其提供了一种固定的流程框架,其中包含了一系列的步骤。这些步骤中,部分可能是通用的、不可变的,构成了算法的基础结构;而其他部分则可以由子类进行个性化的定制和扩展。通过这样的设计,既保证了整体流程的稳定性和一致性,又赋予了子类足够的灵活性来满足不同的具体需求。

模板方法模式的优势显而易见。它增强了代码的复用性,避免了重复代码的出现,使得开发过程更加高效和简洁。同时,它也促进了代码的维护性,因为主要的逻辑结构集中在一个地方,易于理解和修改。此外,通过明确的框架设定,能够更好地规范开发过程,确保不同开发者遵循相同的模式和流程。

在实际应用中,模板方法模式被广泛运用于各种场景。例如,在构建复杂的业务流程时,可以通过模板方法来定义通用的流程框架,然后让各个具体业务根据自身特点来实现特定的步骤。它也常见于各种框架和库的设计中,为开发者提供了一个稳定且可扩展的基础。

以下是一个用 C#实现模板方法模式的示例代码:

using System;

// 抽象类定义模板方法
abstract class TemplateClass
{
    // 模板方法
    public void TemplateMethod()
    {
        Step1();
        Step2();
        Step3();
    }

    protected abstract void Step1();
    protected abstract void Step2();
    protected abstract void Step3();
}

// 具体类 1 实现具体步骤
class ConcreteClass1 : TemplateClass
{
    protected override void Step1()
    {
        Console.WriteLine("ConcreteClass1 执行步骤 1");
    }

    protected override void Step2()
    {
        Console.WriteLine("ConcreteClass1 执行步骤 2");
    }

    protected override void Step3()
    {
        Console.WriteLine("ConcreteClass1 执行步骤 3");
    }
}

// 具体类 2 实现具体步骤
class ConcreteClass2 : TemplateClass
{
    protected override void Step1()
    {
        Console.WriteLine("ConcreteClass2 执行步骤 1");
    }

    protected override void Step2()
    {
        Console.WriteLine("ConcreteClass2 执行步骤 2");
    }

    protected override void Step3()
    {
        Console.WriteLine("ConcreteClass2 执行步骤 3");
    }
}

class Program
{
    static void Main()
    {
        TemplateClass class1 = new ConcreteClass1();
        TemplateClass class2 = new ConcreteClass2();

        class1.TemplateMethod();
        Console.WriteLine();
        class2.TemplateMethod();
    }
}

总之,模板方法模式以其独特的优势和灵活性,在软件开发中占据着重要的地位,为构建高质量、可维护和可扩展的软件系统提供了有力的支持。
如何运用模板方法模式解决实际问题?
首先,明确问题中的固定流程和可变化部分。例如,在一个数据处理任务中,读取数据、进行初步处理、执行核心算法、输出结果等步骤可能是相对固定的,但具体的初步处理细节和核心算法的实现可以是不同的。

然后,设计一个抽象类来定义模板方法,该方法包含了整个固定流程。在这个抽象类中,将可变化的步骤定义为抽象方法,留待具体的子类去实现。

接着,创建具体的子类来继承抽象类。在子类中,根据实际需求实现那些抽象方法,从而定制化特定的行为。

比如,在一个文件处理的场景中,抽象类可以定义打开文件、读取内容、处理内容(抽象方法)、保存结果等步骤。不同类型文件的处理子类可以实现各自独特的处理内容方法。

在一个电商订单处理的例子中,抽象类可以有接收订单、订单验证、计算价格(抽象方法)、生成订单记录等流程。不同业务规则的子类可以在计算价格步骤中实现符合自身业务的算法。

通过这种方式,利用模板方法模式可以实现代码的复用和灵活定制,更好地应对各种实际问题中既有共性又有个性差异的情况。

三、观察者模式:定义对象间的一种一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。

在观察者模式中,存在着主体和多个观察者。主体负责维护一系列与之相关联的观察者对象。当主体的状态发生变化时,它会自动通知所有注册的观察者,让他们能够及时响应并进行相应的动作。

这种模式的优点显著。它实现了主体和观察者之间的松散耦合,使得它们可以相对独立地发展和变化,而不会过度相互影响。同时,通过这种一对多的通知机制,能够高效地传播信息,确保相关方都能及时获取到重要的状态变化。

在实际应用中,它有广泛的用途。比如在图形用户界面中,当数据模型发生变化时,可以通知视图进行更新;在消息系统中,消息发布者可以将消息发送给所有订阅的观察者;在分布式系统中,也可以通过观察者模式来实现节点之间的状态同步等。

以下是一个使用 C#实现观察者模式的示例代码:

using System;
using System.Collections.Generic;

// 抽象观察者
interface IObserver
{
    void Update(string message);
}

// 具体观察者 1
class Observer1 : IObserver
{
    public void Update(string message)
    {
        Console.WriteLine("Observer1 收到消息: " + message);
    }
}

// 具体观察者 2
class Observer2 : IObserver
{
    public void Update(string message)
    {
        Console.WriteLine("Observer2 收到消息: " + message);
    }
}

// 主题
class Subject
{
    private List<IObserver> observers = new List<IObserver>();

    public void Attach(IObserver observer)
    {
        observers.Add(observer);
    }

    public void Detach(IObserver observer)
    {
        observers.Remove(observer);
    }

    public void Notify(string message)
    {
        foreach (var observer in observers)
        {
            observer.Update(message);
        }
    }
}

class Program
{
    static void Main()
    {
        Subject subject = new Subject();

        Observer1 observer1 = new Observer1();
        Observer2 observer2 = new Observer2();

        subject.Attach(observer1);
        subject.Attach(observer2);

        subject.Notify("有新消息啦");
    }
}

观察者模式为构建灵活、可扩展和易于维护的系统提供了有力的支持,让不同的组件之间能够更好地协同工作,适应不断变化的需求和环境。

四、迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

迭代器模式提供了一种方法,可以顺序访问一个聚合对象中的各个元素,而无需暴露该对象的内部表示。它将对集合的遍历操作从集合本身中分离出来,使得遍历代码可以独立于集合的具体实现。

通过迭代器,用户可以方便地逐个访问集合中的元素,而无需关心集合的底层存储结构和遍历算法。迭代器定义了基本的遍历操作,如获取下一个元素、判断是否还有元素等。

这种模式带来了诸多好处。它增强了代码的可维护性和可扩展性,当集合的实现发生变化时,只需要相应地调整迭代器的实现,而不会影响到使用迭代器进行遍历的代码。同时,迭代器模式使得遍历操作更加标准化和统一化,不同类型的集合可以提供符合标准的迭代器,方便代码的复用。

以下是一个用 C#实现迭代器模式的示例代码:

using System;
using System.Collections;
using System.Collections.Generic;

// 聚合接口
interface IAggregate
{
    IIterator CreateIterator();
}

// 具体聚合
class ConcreteAggregate : IAggregate
{
    private List<string> items = new List<string>();

    public void AddItem(string item)
    {
        items.Add(item);
    }

    public IIterator CreateIterator()
    {
        return new ConcreteIterator(this);
    }

    public int Count
    {
        get { return items.Count; }
    }

    public string GetItem(int index)
    {
        return items[index];
    }
}

// 迭代器接口
interface IIterator
{
    bool HasNext();
    object Next();
}

// 具体迭代器
class ConcreteIterator : IIterator
{
    private ConcreteAggregate aggregate;
    private int currentIndex = 0;

    public ConcreteIterator(ConcreteAggregate aggregate)
    {
        this.aggregate = aggregate;
    }

    public bool HasNext()
    {
        return currentIndex < aggregate.Count;
    }

    public object Next()
    {
        if (HasNext())
        {
            string item = aggregate.GetItem(currentIndex);
            currentIndex++;
            return item;
        }
        return null;
    }
}

class Program
{
    static void Main()
    {
        ConcreteAggregate aggregate = new ConcreteAggregate();

        aggregate.AddItem("苹果");
        aggregate.AddItem("香蕉");
        aggregate.AddItem("橘子");

        IIterator iterator = aggregate.CreateIterator();

        while (iterator.HasNext())
        {
            Console.WriteLine(iterator.Next());
        }
    }
}

在实际编程中,迭代器模式在各种数据结构和集合框架中都有广泛的应用。无论是数组、链表、树等,都可以通过迭代器来提供简洁高效的遍历方式。它使得对大量数据的处理和操作变得更加灵活和便捷。

总之,迭代器模式是一种非常实用和重要的设计模式,它在构建复杂的软件系统中发挥着不可或缺的作用,为高效、灵活地处理和遍历集合提供了有力的支持。

五、命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。

在命令模式中,将一个请求封装为一个对象,从而使请求的发送者和请求的执行者相互解耦。这样一来,发送者无需知道请求具体是如何被执行的,只需要发出命令对象即可。

其优势在于极大地提高了系统的灵活性和可扩展性。可以方便地添加、修改或删除命令,而不会对其他部分产生较大影响。同时,通过命令对象的封装,使得命令的管理和操作更加方便和有序。

在实际场景中,命令模式有着广泛的应用。例如在图形界面编程中,各种操作可以被封装为命令对象,如点击按钮执行的操作等。在分布式系统中,也可以通过命令模式来实现不同节点之间的指令传递和执行。
以下是一个用 C#实现命令模式的示例代码:

using System;

// 命令接口
interface ICommand
{
    void Execute();
}

// 具体命令 1
class Command1 : ICommand
{
    private Receiver receiver;

    public Command1(Receiver receiver)
    {
        this.receiver = receiver;
    }

    public void Execute()
    {
        receiver.Action1();
    }
}

// 具体命令 2
class Command2 : ICommand
{
    private Receiver receiver;

    public Command2(Receiver receiver)
    {
        this.receiver = receiver;
    }

    public void Execute()
    {
        receiver.Action2();
    }
}

// 接收者
class Receiver
{
    public void Action1()
    {
        Console.WriteLine("执行动作 1");
    }

    public void Action2()
    {
        Console.WriteLine("执行动作 2");
    }
}

// 调用者
class Invoker
{
    private ICommand command;

    public void SetCommand(ICommand command)
    {
        this.command = command;
    }

    public void ExecuteCommand()
    {
        command.Execute();
    }
}

class Program
{
    static void Main()
    {
        Receiver receiver = new Receiver();

        Command1 command1 = new Command1(receiver);
        Command2 command2 = new Command2(receiver);

        Invoker invoker = new Invoker();

        invoker.SetCommand(command1);
        invoker.ExecuteCommand();

        invoker.SetCommand(command2);
        invoker.ExecuteCommand();
    }
}

此外,命令模式还能帮助实现事务操作,将一系列相关的命令组合起来,实现整体的执行或回滚。它还能对命令进行排队、记录和重放等操作,为系统提供了更强大的功能和控制。

总之,命令模式以其独特的设计理念和优势,在软件设计中占据着重要的地位,为构建复杂而灵活的系统提供了有力的支持。

六、状态模式:允许一个对象在其内部状态改变时改变它的行为。

状态模式的核心在于将对象的状态封装成独立的类,让对象在不同的状态下表现出不同的行为。通过这种方式,将状态的变化和与状态相关的行为紧密结合在一起,而不是将它们混杂在一个庞大的类中。

这种模式带来了诸多优点。它使得状态的转换和行为的处理更加清晰和直观,降低了代码的复杂性和维护难度。每个状态类只专注于处理自身状态相关的行为,提高了代码的可读性和可理解性。同时,它也方便了状态的扩展和新增,当需要添加新的状态时,只需创建相应的状态类并实现相关行为即可。

在实际应用中,状态模式常见于各种具有多种状态且状态间行为差异较大的场景。比如在工作流系统中,不同的流程节点可以视为不同的状态;在游戏开发中,角色的不同状态也可以运用状态模式来进行管理。

以下是一个用 C#实现状态模式的示例代码:

using System;

// 状态接口
interface IState
{
    void Handle(Context context);
}

// 具体状态 A
class StateA : IState
{
    public void Handle(Context context)
    {
        Console.WriteLine("当前状态为 StateA");
        context.SetState(new StateB());
    }
}

// 具体状态 B
class StateB : IState
{
    public void Handle(Context context)
    {
        Console.WriteLine("当前状态为 StateB");
        context.SetState(new StateA());
    }
}

// 上下文类
class Context
{
    private IState state;

    public Context()
    {
        state = new StateA();
    }

    public void SetState(IState state)
    {
        this.state = state;
    }

    public void Request()
    {
        state.Handle(this);
    }
}

class Program
{
    static void Main()
    {
        Context context = new Context();

        context.Request();
        context.Request();
        context.Request();
    }
}

通过状态模式,可以更好地管理和控制对象的状态变化,提高系统的灵活性和可扩展性,为构建复杂而高效的软件系统提供有力的支撑。

总之,状态模式凭借其独特的设计思路和优势,在软件开发中具有重要的地位和广泛的应用价值。

七、中介者模式:用一个中介对象来封装一系列的对象交互。

中介者模式定义了一个中介对象来封装一系列对象之间的交互。通过中介者,各个对象之间无需直接相互通信,而是通过与中介者进行交互来协调彼此的行为。

这种模式的优点显著。它减少了对象之间的直接依赖和复杂的交互关系,使得系统的结构更加清晰和易于管理。中介者可以集中处理对象之间的通信逻辑,避免了大量的点对点通信代码,提高了代码的可读性和可维护性。

在实际运用中,中介者模式常用于具有多个相互关联且交互复杂的对象的场景。例如,在一个大型的用户界面系统中,多个组件之间的交互可以通过中介者来协调;在分布式系统中,不同节点之间的通信也可以借助中介者来进行管理和调度。

以下是一个用 C#实现中介者模式的示例代码:

using System;

// 抽象同事类
abstract class Colleague
{
    protected IMediator mediator;

    public Colleague(IMediator mediator)
    {
        this.mediator = mediator;
    }

    public abstract void Send(string message);
    public abstract void Receive(string message);
}

// 具体同事 A
class ColleagueA : Colleague
{
    public ColleagueA(IMediator mediator) : base(mediator)
    {
    }

    public override void Send(string message)
    {
        mediator.SendMessage(this, message);
    }

    public override void Receive(string message)
    {
        Console.WriteLine("ColleagueA 收到消息: " + message);
    }
}

// 具体同事 B
class ColleagueB : Colleague
{
    public ColleagueB(IMediator mediator) : base(mediator)
    {
    }

    public override void Send(string message)
    {
        mediator.SendMessage(this, message);
    }

    public override void Receive(string message)
    {
        Console.WriteLine("ColleagueB 收到消息: " + message);
    }
}

// 中介者接口
interface IMediator
{
    void SendMessage(Colleague colleague, string message);
}

// 具体中介者
class ConcreteMediator : IMediator
{
    private ColleagueA colleagueA;
    private ColleagueB colleagueB;

    public void RegisterA(ColleagueA colleagueA)
    {
        this.colleagueA = colleagueA;
    }

    public void RegisterB(ColleagueB colleagueB)
    {
        this.colleagueB = colleagueB;
    }

    public override void SendMessage(Colleague colleague, string message)
    {
        if (colleague == colleagueA)
        {
            colleagueB.Receive(message);
        }
        else if (colleague == colleagueB)
        {
            colleagueA.Receive(message);
        }
    }
}

class Program
{
    static void Main()
    {
        ConcreteMediator mediator = new ConcreteMediator();

        ColleagueA colleagueA = new ColleagueA(mediator);
        ColleagueB colleagueB = new ColleagueB(mediator);

        mediator.RegisterA(colleagueA);
        mediator.RegisterB(colleagueB);

        colleagueA.Send("Hello from A");
        colleagueB.Send("Hi from B");
    }
}

通过中介者模式,可以有效地降低系统的耦合度,增强系统的灵活性和可扩展性。它为构建复杂而有序的软件系统提供了一种有效的解决方案。

总之,中介者模式以其独特的方式,在协调对象之间的交互、优化系统结构方面发挥着重要作用,是软件开发中值得深入研究和应用的一种模式。

八、 备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

它主要用于捕获和保存一个对象的内部状态,以便在需要的时候能够恢复到该状态。这就像是给对象的状态拍了一个“快照”,可以随时回退到这个特定的状态。

这种模式的好处在于,它能够在不破坏对象封装性的前提下,方便地记录和恢复状态。它为系统提供了一种灵活的状态管理机制,可以应对各种需要回滚或恢复的情况。

在实际场景中,比如在游戏中可以保存玩家的进度状态;在文档编辑时可以记录文档的某个时刻的状态等。通过备忘录模式,可以确保在各种情况下都能准确地恢复到之前的状态,给用户带来更好的体验。

以下是一个用 C#实现备忘录模式的示例代码:

using System;

// 备忘录类
class Memento
{
    private int state;

    public Memento(int state)
    {
        this.state = state;
    }

    public int GetState()
    {
        return state;
    }
}

// 原发器类
class Originator
{
    private int state;

    public void SetState(int state)
    {
        this.state = state;
    }

    public int GetState()
    {
        return state;
    }

    public Memento SaveState()
    {
        return new Memento(state);
    }

    public void RestoreState(Memento memento)
    {
        state = memento.GetState();
    }
}

// 管理者类
class Caretaker
{
    private Memento memento;

    public void SaveMemento(Memento memento)
    {
        this.memento = memento;
    }

    public Memento RetrieveMemento()
    {
        return memento;
    }
}

class Program
{
    static void Main()
    {
        Originator originator = new Originator();

        originator.SetState(10);

        Caretaker caretaker = new Caretaker();

        caretaker.SaveMemento(originator.SaveState());

        originator.SetState(20);

        Console.WriteLine("当前状态: " + originator.GetState());

        originator.RestoreState(caretaker.RetrieveMemento());

        Console.WriteLine("恢复后状态: " + originator.GetState());
    }
}

备忘录模式将状态的保存和恢复操作与对象本身解耦,使得系统的设计更加清晰和易于维护。它为软件系统的状态管理提供了一种简洁而有效的方式,是构建可靠和灵活的应用程序的重要工具之一。

总之,备忘录模式在很多情况下都能发挥重要作用,为实现灵活的状态管理提供了有力支持。

九、访问者模式:表示一个作用于某对象结构中的各元素的操作。

在访问者模式中,将数据结构和作用于这些数据结构上的操作分离开来。通过定义一个访问者接口,不同的具体访问者可以实现对数据结构中元素的特定操作。

这种模式的优势在于它提供了一种灵活的方式来扩展对数据结构的操作,而无需修改数据结构本身。它使得可以在不改变数据结构代码的情况下,动态地添加新的访问者和相应的操作。

在实际运用中,访问者模式常常用于一些需要对复杂数据结构进行多样化操作的场景。比如在编译器设计中,对不同的语法结构进行不同的处理;在数据分析中,根据不同的需求对数据进行特定的统计和分析等。

通过访问者模式,可以将操作的变化与数据结构的稳定相分离,提高了系统的可维护性和可扩展性。它为处理复杂的数据结构和操作关系提供了一种有效的解决方案。

以下是一个用 C#实现访问者模式的示例代码:

using System;

// 元素接口
interface IElement
{
    void Accept(IVisitor visitor);
}

// 具体元素 A
class ElementA : IElement
{
    public void Accept(IVisitor visitor)
    {
        visitor.VisitElementA(this);
    }
}

// 具体元素 B
class ElementB : IElement
{
    public void Accept(IVisitor visitor)
    {
        visitor.VisitElementB(this);
    }
}

// 访问者接口
interface IVisitor
{
    void VisitElementA(ElementA element);
    void VisitElementB(ElementB element);
}

// 具体访问者
class ConcreteVisitor : IVisitor
{
    public void VisitElementA(ElementA element)
    {
        Console.WriteLine("访问 ElementA");
    }

    public void VisitElementB(ElementB element)
    {
        Console.WriteLine("访问 ElementB");
    }
}

class Program
{
    static void Main()
    {
        IElement elementA = new ElementA();
        IElement elementB = new ElementB();

        IVisitor visitor = new ConcreteVisitor();

        elementA.accept(visitor);
        elementB.accept(visitor);
    }
}

然而,访问者模式也有其局限性,比如可能会导致系统中类的数量增加,增加一定的复杂性。

总之,访问者模式是一种在特定场景下具有重要价值的设计模式,它为解决数据结构与操作之间的关系提供了独特的思路和方法。

十、责任链路模式

在责任链模式中,多个对象通过前后相连形成一条链。当有请求产生时,沿着这条链依次传递,直到某个对象能够处理该请求为止。

它的优点十分显著。首先,它实现了请求发送者和请求处理者之间的松耦合,使得系统更加灵活。其次,它可以动态地添加或移除责任节点,轻松适应业务的变化。再者,通过责任链的传递,可以根据具体情况进行灵活的处理决策。

在实际场景中,例如在审批流程中,不同级别的审批人员形成责任链,请求依次传递,符合条件的人员进行处理;在消息处理系统中,不同类型的处理器构成责任链,对消息进行分类处理。

以下是一个 C#实现责任链模式的示例代码:

using System;

interface IHandler
{
    void HandleRequest(int request);
}

class Handler1 : IHandler
{
    public void HandleRequest(int request)
    {
        if (request < 10)
        {
            Console.WriteLine("Handler1 处理了请求");
        }
        else
        {
            Console.WriteLine("Handler1 传递请求");
            new Handler2().HandleRequest(request);
        }
    }
}

class Handler2 : IHandler
{
    public void HandleRequest(int request)
    {
        if (request < 20)
        {
            Console.WriteLine("Handler2 处理了请求");
        }
        else
        {
            Console.WriteLine("Handler2 传递请求");
            new Handler3().HandleRequest(request);
        }
    }
}

class Handler3 : IHandler
{
    public void HandleRequest(int request)
    {
        if (request < 30)
        {
            Console.WriteLine("Handler3 处理了请求");
        }
        else
        {
            Console.WriteLine("Handler3 无法处理");
        }
    }
}

class Program
{
    static void Main()
    {
        new Handler1().HandleRequest(15);
    }
}

通过责任链模式,系统能够更加高效地处理各种请求和任务,同时也为系统的扩展和维护提供了便利。它是构建复杂而灵活的系统架构的重要工具之一。

总之,责任链模式以其独特的方式,在组织和处理请求方面发挥着重要作用,为实现高效、灵活的系统提供了有力支持。

十一、解析器模式

解析器模式是一种用于处理语法或表达式解析的设计模式。

该模式将一个复杂的语法分解成小的可重复使用的组件。通过定义不同的解析器对象来处理语法的各个部分,然后将它们组合起来以完成对整个语法的解析。

其优点在于它提供了一种清晰的结构来处理复杂的语法结构,使得代码的组织和维护更加容易。它能够分离语法的定义和解析的逻辑,增强了系统的灵活性和可扩展性。

在实际应用中,解析器模式常用于编译器的构建、配置文件的解析、表达式求值等领域。例如,在编译器中,词法分析器和语法分析器等都是基于解析器模式来实现的。

通过解析器模式,可以有效地将复杂的语法解析任务分解为多个相对简单的子任务,提高了代码的可读性和可理解性。

以下是一个用 C#实现的解析器模式示例代码:

interface IExpression
{
    int Evaluate();
}

class NumberExpression : IExpression
{
    private int number;

    public NumberExpression(int number)
    {
        this.number = number;
    }

    public int Evaluate()
    {
        return number;
    }
}

class AddExpression : IExpression
{
    private IExpression left;
    private IExpression right;

    public AddExpression(IExpression left, IExpression right)
    {
        this.left = left;
        this.right = right;
    }

    public int Evaluate()
    {
        return left.Evaluate() + right.Evaluate();
    }
}

class Program
{
    static void Main()
    {
        IExpression five = new NumberExpression(5);
        IExpression three = new NumberExpression(3);

        IExpression sum = new AddExpression(five, three);

        Console.WriteLine("结果: " + sum.Evaluate());
    }
}

然而,该模式也存在一些挑战,比如对于复杂语法的设计和实现可能会较为困难和繁琐。

总之,解析器模式在处理特定的语法解析问题上具有重要地位,为构建高效、准确的解析系统提供了有力的方法和思路。


总结:
面向对象设计原则:
  1. 哪里有变化,就封装哪里;
  2. 面向抽象编程,细节和高层实现都要依赖抽象;
  3. 多组合,少继承。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值