【設計模式】之狀態模式

  • UML

  • 原型

//狀態抽象類
abstract class State
    {
        public abstract void Handle(Context context);
    }
    
//狀態A
 class ConcreteStateA : State
    {
        public override void Handle(Context context)
        {
            context.State = new ConcreteStateB();
        }
    }
//狀態B
class ConcreteStateB : State
    {
        public override void Handle(Context context)
        {
            context.State = new ConcreteStateA();
        }
    }
//上下文
class Context
    {
        private State state;
        public Context(State state)
        {
            this.state = state;
        }
        public void Request()
        {
            state.Handle(this);
        }
        public State State { get => state; set => state = value; }
    }
 class Program
    {
        static void Main(string[] args)
        {
            Context c = new Context(new ConcreteStateA());
            c.Request();
            c.Request();
            c.Request();
            c.Request();
        }
    }
  • 舉例

一個簡單的停等協議:

 //分組
    class Packet
    {
        private string data;            //數據
        private string checksum;        //數據校驗和
        private int num;                //序號

        public string Data { get => data; set => data = value; }
        public string Checksum { get => checksum; set => checksum = value; }
        public int Num { get => num; set => num = value; }
    }
 //狀態抽象類
    abstract class State
    {
        public abstract void Change(Context context);
    }
//終端抽象類
    abstract class Context
    {
        private State state;            //狀態
        private string data;            //數據
        private string checksum;        //校驗和
        private Packet packet;          //分組
        private Context other;          //對等方
        //初始化狀態
        public Context(State state)
        {
            this.state = state;
        }
        //運行
        public void Run()
        {
            state.Change(this);
        }
        //rdt發送
        public bool rdt_send(string data)
        {
            return true;
        }
        //rdt接收
        public bool rdt_rcv(Packet packet)
        {
            return true;
        }
        //裝包
        public Packet make_pkt(int num,string data,string checksum)
        {
            Console.WriteLine($"初始化分組[{num},{data},{checksum}]...");
            Packet packet = new Packet();
            packet.Num = num;
            packet.Data = data;
            packet.Checksum = checksum;
            return packet;
        }
        //udt發送
        public void udt_send(Packet packet)
        {
            Console.WriteLine("發送...");
            //%50的出錯概率
            if (Program.random.Next(0,100)<=50)
            {
                packet.Data = "error";
                Console.WriteLine("出現bit差錯!");
            }
            Other.Packet = packet;
        }
        //解包
        public void extract(Packet packet, out string data)
        {
            Console.WriteLine($"解析分組...");
            data = packet.Data;
        }
        //上傳給高層
        public void deliver_data(string data)
        {
            Console.WriteLine($"{data}");
        }
        //校驗和
        public bool corrupt(Packet rcvpkt)
        {
            if(!rcvpkt.Data.Equals(rcvpkt.Checksum))
            {
                Console.WriteLine("分組出錯!");
                return true;
            }
            else
            {
                return false;
            }
        }
        public bool notcorrupt(Packet rcvpkt)
        {
            if (rcvpkt.Data.Equals(rcvpkt.Checksum))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        //肯定確認
        public bool isACK(Packet rcvpkt,int num)
        {
            if (rcvpkt.Data.Equals("ACK")&&rcvpkt.Num==num)
            {
                Console.WriteLine($"收到一個{num}號肯定確認!");
                return true;
            }
            else
            {
                return false;
            }
        }
        //是0號分組還是1號分組
        public bool has_seq0(Packet packet)
        {
            if(packet.Num==0)
            {
                Console.WriteLine("收到了0號分組");
                return true;
            }else
            {
                return false;

            }
        }
        public bool has_seq1(Packet packet)
        {
            if (packet.Num == 1)
            {
                Console.WriteLine("收到了1號分組");
                return true;
            }
            else
            {
                return false;

            }
        }

        public State State { get => state; set => state = value; }
        public string Data { get => data; set => data = value; }
        public Context Other { get => other; set => other = value; }
        public Packet Packet { get => packet; set => packet = value; }
        public string Checksum { get => checksum; set => checksum = value; }
    }
 //發送端
    class Sender : Context
    {
        public Sender(State state) : base(state)
        {
        }
    }
// 發送端狀態A
    class SenderStateA : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Sender:=>A");
            Console.WriteLine("---------------------");
            if (context.rdt_send(context.Data))
            {
                Packet packet = context.make_pkt(0,context.Data, context.Checksum);
                context.udt_send(packet);
                context.State = new SenderStateB();

                //接收端處理
                context.Other.Run();
            } 
        }
    }
// 發送端狀態B
class SenderStateB : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Sender:=>B");
            Console.WriteLine("---------------------");
            Console.WriteLine("接收...");

            if (context.rdt_rcv(context.Packet) && (context.corrupt(context.Packet) || context.isACK(context.Packet,1)))
            {
                Packet packet = context.make_pkt(0, context.Data, context.Checksum);
                context.udt_send(packet);

                context.Other.Run();
            }else if (context.rdt_rcv(context.Packet)&& context.notcorrupt(context.Packet) && context.isACK(context.Packet,0))
            {
                context.State = new SenderStateC();
            }
        }
    }
//發送端狀態C
class SenderStateC : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Sender:=>C");
            Console.WriteLine("---------------------");
            if (context.rdt_send(context.Data))
            {
                Packet packet = context.make_pkt(1, context.Data, context.Checksum);
                context.udt_send(packet);
                context.State = new SenderStateD();
                //接收端處理
                context.Other.Run();
            }
        }
    }
// 發送端狀態D
class SenderStateD : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Sender:=>D");
            Console.WriteLine("---------------------");
            Console.WriteLine("接收...");

            if (context.rdt_rcv(context.Packet) && (context.corrupt(context.Packet) || context.isACK(context.Packet,0)))
            {
                Packet packet = context.make_pkt(1, context.Data, context.Checksum);
                context.udt_send(packet);

                context.Other.Run();
            }else if (context.rdt_rcv(context.Packet) && context.notcorrupt(context.Packet) && context.isACK(context.Packet,1))
            {
                context.State = new SenderStateA();
            }
        }
    }
//接收端
    class Receiver:Context
    {
        public Receiver(State state):base(state)
        {
        }
    }
//接收端狀態A
    class RcvStateA : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Receiver:=>A");
            Console.WriteLine("------------------------");
            Console.WriteLine("接收...");

            if (context.rdt_rcv(context.Packet) && (context.corrupt(context.Packet) || context.has_seq1(context.Packet)))
            {
                Packet packet = context.make_pkt(1,"ACK", "ACK");
                context.udt_send(packet);

                context.Other.Run();
            }
            else if(context.rdt_rcv(context.Packet) && context.notcorrupt(context.Packet) && context.has_seq0(context.Packet))
            {
                string data = "";
                context.extract(context.Packet,out data);
                context.deliver_data(data);
                Packet packet = context.make_pkt(0,"ACK","ACK");
                context.udt_send(packet);

                context.State = new RcvStateB();

                context.Other.Run();
            }
        }
    }
// 接收端狀態B
class RcvStateB : State
    {
        public override void Change(Context context)
        {
            Console.WriteLine("Receiver:=>B");
            Console.WriteLine("------------------------");
            Console.WriteLine("接收...");

            if (context.rdt_rcv(context.Packet) && (context.corrupt(context.Packet) || context.has_seq0(context.Packet)))
            {
                Packet packet = context.make_pkt(0,"ACK", "ACK");
                context.udt_send(packet);

                context.Other.Run();
            }
            else if (context.rdt_rcv(context.Packet) && context.notcorrupt(context.Packet) && context.has_seq1(context.Packet))
            {
                string data = "";
                context.extract(context.Packet, out data);
                context.deliver_data(data);
                Packet packet = context.make_pkt(1,"ACK", "ACK");
                context.udt_send(packet);

                context.State = new RcvStateA();

                context.Other.Run();
            }
        }
    }
class Program
    {
        //產生隨機數用於模仿出錯概率
        public static readonly Random random = new Random();

        static void Main(string[] args)
        {
            Sender sender = new Sender(new SenderStateA());
            Receiver receiver = new Receiver(new RcvStateA());
            //建立連接
            sender.Other = receiver;
            receiver.Other = sender;

            sender.Data = "hello ";
            sender.Checksum = "hello ";
            sender.Run();
            sender.Data = "world!";
            sender.Checksum = "world!";
            sender.Run();
            Console.WriteLine("-----------SUCCESS-----------");
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章