《GOF设计模式》—状态(STATE)—Delphi源码示例:网络连接

本文通过一个TCP连接类的例子,展示了状态模式在实现不同状态下的行为变化。包括连接建立、监听、关闭等多个状态及其间的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例:网络连接
说明:
考虑一个表示网络连接的类TCPConnection。一个TCPConnection对象的状态处于若干不同状态之一:连接已建立(Established)、正在监听(Listening)、连接已关闭(Closed)。State模式描述了TCPConnection如何在每一种状态下表现出不同的行为。

clip_image002

代码:
 
unit uTCPConnection;

interface

uses
    SysUtils, Classes,Dialogs;

type
    TTCPState = class;
    TTCPOctetStream = class
    end;

    TTCPConnection = class
    private
        FState: TTCPState;
        procedure ChangeState(s: TTCPState);
    public
        constructor Create;
        //---
        procedure ActiveOpen();  //--主动打开连接
        procedure PassiveOpen(); //--被动打开连接
        procedure Close();
        procedure Send();        //--发送
        procedure Acknowledge(); //--应答
        procedure Synchronize();
        //---
        procedure ProcessOctet(os: TTCPOctetStream);  //--处理字节流
    end;

    TTCPState = class
    protected
        procedure ChangeState(c: TTCPConnection; s: TTCPState);
    public
        procedure ActiveOpen(c: TTCPConnection); virtual;
        procedure PassiveOpen(c: TTCPConnection); virtual;
        procedure Close(c: TTCPConnection); virtual;
        procedure Send(c: TTCPConnection); virtual;
        procedure Acknowledge(c: TTCPConnection); virtual;
        procedure Synchronize(c: TTCPConnection); virtual;
        procedure Transmit(c: TTCPConnection; os: TTCPOctetStream); virtual;
    end;

    TTCPClosed = class(TTCPState)      //--连接已关闭
    public
        constructor Create;
        destructor Destroy; override;
        //---
        class function Instance(): TTCPState;
        //---
        procedure ActiveOpen(c: TTCPConnection); override;  //--主动打开连接
        procedure PassiveOpen(c: TTCPConnection); override; //--被动打开连接
    end;

    TTCPEstablished = class(TTCPState)  //--连接已建立,数据传输状态
    public
        constructor Create;
        destructor Destroy; override;
        //---
        class function Instance(): TTCPState;
        //---
        procedure Close(c: TTCPConnection); override;
        procedure Send(c: TTCPConnection); override;
        procedure Transmit(c: TTCPConnection; os: TTCPOctetStream);  override;
    end;

    TTCPListening = class(TTCPState)  //--正在监听
    public
        constructor Create;
        destructor Destroy; override;
        procedure Acknowledge(c: TTCPConnection); override;
        //---
        class function Instance(): TTCPState;
        //---
        procedure Send(c: TTCPConnection); override;
    end;

procedure Test;

implementation

var
    FTCPClosed: TTCPClosed;
    FTCPEstablished: TTCPEstablished;
    FTCPListening: TTCPListening;

procedure Test;
    //---
    procedure _TCPClient;
    var
        AClient:TTCPConnection;
    begin
        AClient := TTCPConnection.Create;
        try
            with AClient do
            begin
                ActiveOpen;
                Send;
                Close;
            end;
        finally
            AClient.Free;
        end;
    end;
    //---
    procedure _TCPServer;
    var
        AServer:TTCPConnection;
    begin
        AServer := TTCPConnection.Create;
        try
            with AServer do
            begin
                PassiveOpen;
                //---
                Acknowledge;
                Send;
                Send;
                //---
                Close;
            end;
        finally
            AServer.Free;
        end;
    end;
begin
    //_TCPClient;
    _TCPServer;
end;

procedure TTCPConnection.ChangeState(s: TTCPState);
begin
    FState := s;
end;

constructor TTCPConnection.Create;
begin
    inherited;
    //---
    FState := TTCPClosed.Instance;
end;

procedure TTCPConnection.ActiveOpen();
begin
    FState.ActiveOpen(self);
end;

procedure TTCPConnection.PassiveOpen();
begin
    FState.PassiveOpen(self);
end;

procedure TTCPConnection.Close();
begin
    FState.Close(self);
end;

procedure TTCPConnection.Send();
begin
    FState.Send(self);
end;

procedure TTCPConnection.Acknowledge();
begin
    FState.Acknowledge(self);
end;

procedure TTCPConnection.Synchronize();
begin
    FState.Synchronize(self);
end;

procedure TTCPConnection.ProcessOctet(os: TTCPOctetStream);
begin
end;

procedure TTCPState.ChangeState(c: TTCPConnection; s: TTCPState);
begin
    c.ChangeState(s);
end;

procedure TTCPState.Transmit(c: TTCPConnection; os: TTCPOctetStream);
begin
end;

procedure TTCPState.ActiveOpen(c: TTCPConnection);
begin
end;

procedure TTCPState.PassiveOpen(c: TTCPConnection);
begin
end;

procedure TTCPState.Close(c: TTCPConnection);
begin
end;

procedure TTCPState.Synchronize(c: TTCPConnection);
begin
end;

procedure TTCPState.Acknowledge(c: TTCPConnection);
begin
end;

procedure TTCPState.Send(c: TTCPConnection);
begin
end;

class function TTCPClosed.Instance(): TTCPState;
begin
    if FTCPClosed = nil then
        FTCPClosed := TTCPClosed.Create;
    //---
    result := FTCPClosed;
end;

procedure TTCPClosed.ActiveOpen(c: TTCPConnection);
{
SYN是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,
客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了这个消息,
最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,
数据才可以在客户机和服务器之间传递。
}
begin
    //发送SYN,接收SYN,ACK等
    ChangeState(c,TTCPEstablished.Instance);
end;

procedure TTCPClosed.PassiveOpen(c: TTCPConnection);
begin
    ChangeState(c,TTCPListening.Instance);
end;

procedure TTCPEstablished.Transmit(c: TTCPConnection; os: TTCPOctetStream);
begin
    c.ProcessOctet(os);
end;

procedure TTCPEstablished.Close(c: TTCPConnection);
{FIN是用来扫描保留的端口,发送一个FIN包(或者是任何没有ACK或SYN标记的包)到目标的一个开放的端口,
然后等待回应。许多系统会返回一个复位标记。 }
begin
    //发送FIN,接收ACK OF FIN等
    ChangeState(c,TTCPListening.Instance);
end;

constructor TTCPListening.Create;
begin
    if FTCPListening = nil then
        FTCPListening := Self
    else
        raise Exception.Create('Error');
end;

destructor TTCPListening.Destroy;
begin
    FTCPListening := nil;
    //---
    inherited;
end;

procedure TTCPListening.Acknowledge(c: TTCPConnection);
begin
    ShowMessage('Listening.Acknowledge');
end;

class function TTCPListening.Instance: TTCPState;
begin
    if FTCPListening = nil then
        FTCPListening := TTCPListening.Create;
    //---
    result := FTCPListening;
end;

procedure TTCPListening.Send(c: TTCPConnection);
begin
    //发送SYN,接收SYN,ACK等
    ChangeState(c,TTCPEstablished.Instance);
end;

constructor TTCPEstablished.Create;
begin
    if FTCPEstablished = nil then
        FTCPEstablished := Self
    else
        raise Exception.Create('Error');
end;

destructor TTCPEstablished.Destroy;
begin
    FTCPEstablished := nil;
    //---
    inherited;
end;

class function TTCPEstablished.Instance: TTCPState;
begin
    if FTCPEstablished = nil then
        FTCPEstablished := TTCPEstablished.Create;
    //---
    result := FTCPEstablished;
end;

procedure TTCPEstablished.Send(c: TTCPConnection);
begin
    ShowMessage('Established.Send');
end;

constructor TTCPClosed.Create;
begin
    if FTCPClosed = nil then
        FTCPClosed := Self
    else
        raise Exception.Create('Error');
end;

destructor TTCPClosed.Destroy;
begin
    FTCPClosed := nil;
    //---
    inherited;
end;

initialization
    FTCPClosed := nil;
    FTCPEstablished := nil;
    FTCPListening := nil;

finalization
    if FTCPClosed <> nil then
        FTCPClosed.Free;
    if FTCPEstablished <> nil then
        FTCPEstablished.Free;
    if FTCPListening <> nil then
        FTCPListening.Free;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值