zoukankan      html  css  js  c++  java
  • 设计模式-单例模式,观察者模式

    序言

    点击查看:设计模式系列

    咳咳,今天起,我要把对设计模式的理解心得,用全新的案例去分析,分享给大家。希望大家能够喜欢。

    观察者模式

    举例阐述:游戏情节,一颗小男孩,丢到众多鬼子附近,爆炸啦,根据炸弹的威力计算爆炸后鬼子的血量,假定有些鬼子有防具,有些鬼子没有防具。

    分析:这种情况,使用观察者模式是比较理想的,因为观察者模式的就是是处理对象间一对多的依赖关系的,当一个对象发生变化,其它依赖他的对象都要得到通知并更新。

    定义:在观察者模式中,上述小男孩被称为主题,而小鬼子们就被称为观察者。

    下面我用代码,把举例给演示出来。

    定义观察者模式中的主题。

       //炸弹
        public class bomb
        { 
            //炸弹名称
            public  string Name;
            //炸弹攻击距离
            public  int Length;
            //炸弹攻击力
            public int ATK;
            //简单期间,这里炸弹我只有一颗啦。
            public bomb()
            {
                Name = "小男孩";
                Length = 100;
                ATK = 1000;
            }
    
            public DeBeng debeng;
    
            //爆炸
            public void beng()
            {
                if (debeng != null)
                {
                    debeng(this);
                }
            }
        }
       
        //定义委托,为啦添加爆炸影响的路人
        public delegate void DeBeng(bomb bomb);

    定义观察者模式中的观察者

    //观察者,路人
        public class roadPeople
        { 
            //离炸弹距离
            public  int Length;
            //路人名称
            public  string Name;
            //血量
            public int LifeLength;
            //盾抵抗力
            public int ShieldLth;
            /// <summary>
            /// 初始化路人
            /// </summary>
            /// <param name="name">名称</param>
            /// <param name="lgth">炸弹距离</param>
            /// <param name="llth">生命值</param>
            /// <param name="sth">抵抗能力</param>
            public roadPeople(string name, int lgth,int llth,int sth)
            {
                Length = lgth;
                Name = name;
                LifeLength = llth;
                ShieldLth = sth;
            }
            //被炸,这里的处理方法我写一致啦,其实可以是根据不同的柜子有不一样的处理方式,这样就展示啦观察者模式的强大,我这里为啦简便起见,就没有定义那么多类
            public void Beated(bomb bom)   
            {
                //盾削去攻击
                int th=this.ShieldLth-bom.ATK;
                //被炸后,血量情况
                string info="";
                if (th > 0)
                { 
                    //盾牛逼,不掉血
                    info = "我是:" + this.Name + "。我的盾更牛逼不掉血" ;               
                }
                else
                {
                    //掉血
                    int h=th+this.LifeLength;
                    //判断死亡
                    if (h>0)
                    {
                        //未死
                        info = "我是:" + this.Name + "。掉血:" + (-th)+"点。";
                    }
                    else
                    {
                        //已死
                        info = "我是:" + this.Name + "。最后一句话,但愿苍老师随我而去!";
                    }
                }
                Console.WriteLine("啊,哦,额,噗,我靠,牛逼。"+ info);
            }
        }

    使用主题与观察者

    static void Main()
            {
               //路人集合
                List<roadPeople> list = new List<roadPeople>() { 
               //路人甲,距离炸弹10米,血量100,带1级盾
                new roadPeople("路人甲",40,100,1),
                //路人乙,距离炸弹20米,血量1000,带10级盾
                new roadPeople("路人乙",40,100,4000),
                new roadPeople("路人丙",50,2000,50),
                new roadPeople("路人丁",1000,30,1)         
               };
    
                //实例化炸弹
                bomb bom = new bomb();
                //添加能炸到的路人
                foreach(roadPeople rp in list)
                {
                    if ((bom.Length - rp.Length) > 0)
                    {
                        bom.debeng += new DeBeng(rp.Beated);                    
                    }
                }
                //炸弹爆炸
                bom.beng();
                Console.ReadLine();
            }

    运行结果

    简单阐述构建使用观察者模式过程:主题可变更做为参数,观察者拥有自己的属性与同样签名的响应方法,把各个观察者对象的被炸方法添加到事件中,然后把主题对象作为参数传递给事件中,这样就能根据观察者各自的属性,与计算方法来获取通知更新。

    观察者模式的效果:观察者促进啦主体的抽象耦合。主体不知道观察者的细节,观察者可根据自身的属性功能来对主题的通知做变更。然而观察者也有自己的缺点,就是当主题发生一系列的变化事,观察者都要做批量的更新,如果这样的更新成本很高,那么解决方法就是根据种类需求通知,而不能盲目的通知所有的观察者。

    单例模式(单件模式)

    案例:你只有一个老爸,你妈只有一个老公,然而他是同一个人,晚上你们吃过饭,你就让你爸给你讲你小时候的事,你妈让你爸讲她们谈恋爱时候的事,老爸说除啦你们两个其它人是没有这待遇的。

    分析:这种情况下,老爸只有一个,不能多次创建,就很适合使用单例模式。

    单例模式:首先要确定老爸不能被多次创建,因为老爸只有一个,使我们的唯一。

    单例模式中的单件确保类有且仅有一个

     //单例中的Dad有且仅有一个
        public class Dad
        {
            //老爸
            static Dad dad = null;
            static readonly object padlock = new object();
            Dad()
            {
                //吃饱,先休息2秒
                Thread.Sleep(2000);
            }
    
            ///故事内容
            private string content = "";
            ///讲故事 
            public void  tell()
            {
                lock (padlock)
                {
                    if (Thread.CurrentThread.Name == "mama")
                    {
                        content = "老婆那画面太美,我不敢想!";
                    }
                    else if (Thread.CurrentThread.Name == "me")
                    {
                        content = "儿子,你小时候最乖啦,我们都很爱你。";
                    }
                    else
                    {
                        content = "除来老婆和孩子,别人休想让我讲故事!";
                    }
                }
            }
    
            ///获得故事内容
            public string GetCounter()
            {
                return content;
            }
    
            //老爸只有一个,不能被多次创建,叫一下老爸,老爸就会出现
            public static Dad sayDad
            {
                get
                {
                    if (dad == null)
                    {
                        lock (padlock)
                        {
                            if (dad == null)
                            {
                                dad = new Dad();
                            }
                        }
                    }
                    return dad;
                }
            }
        }

    使用单件对象

     /// <summary>
            /// 线程工作
            /// </summary>
            public static void DoSomeWork()
            {
                ///构造显示字符串
                string results = "";
    
                ///叫一下老爸,唯一的老爸闪亮登场
                Dad dad = Dad.sayDad;
    
                ///开始讲故事
                dad.tell();
    
                results += "讲给";
                results += Thread.CurrentThread.Name.ToString() + "——〉";
                results += "我想对你说:";
                results += dad.GetCounter().ToString();
                results += "
    ";
                Console.WriteLine(results);
    
                ///清空显示字符串
                results = "";
    
    
            }
    
            //爸爸的世界里,永远有妈妈跟我2个线程
            public void StartMain()
            {
                Thread thread0 = Thread.CurrentThread;
                thread0.Name = "me";
                Thread thread1 = new Thread(new ThreadStart(DoSomeWork));
                thread1.Name = "mama";
                Thread thread2 = new Thread(new ThreadStart(DoSomeWork));
                thread2.Name = "badegg";
                Thread.Sleep(1000);
                thread1.Start();
                Thread.Sleep(1000);
                thread2.Start();
                Thread.Sleep(1000);
                ///线程0也只执行和其他线程相同的工作
                DoSomeWork();
            }

    运行

       public static void Main(string[] args)
            {
                CountMutilThread cmt = new CountMutilThread();
                cmt.StartMain();
                Console.ReadLine();
            }

    结果:

    单例模式:确保单件有且仅有一个实例(不让继承,不让构造等手段),并且提供一个对实例的访问点。

    单例的另外好办法

     public class Dad
        {
            ///存储唯一的实例 
            static Dad dad = new Dad();
    
            //为啦不让实例化
            private Dad()
            {
              
            }
            
            //老爸只有一个,不能被多次创建,叫一下老爸,老爸就会出现
            public static  Dad sayDad()
            {
                return dad;
            }
    
            object ss = new object();
            ///故事内容
            private string content = "";
            ///讲故事 
            public void tell()
            {
                lock (ss)
                {
    
                    if (Thread.CurrentThread.Name == "mama")
                    {
                        content = "老婆那画面太美,我不敢想!";
                    }
                    else if (Thread.CurrentThread.Name == "me")
                    {
                        content = "儿子,你小时候最乖啦,我们都很爱你。";
                    }
                    else
                    {
                        content = "除来老婆和孩子,别人休想让我讲故事!";
                    }
                }
            }
    
            ///获得故事内容
            public string GetCounter()
            {
                return content;
            }
        }
    View Code

     欢迎加入左上方群,交流探讨c#设计模式

  • 相关阅读:
    根据svm将视频帧转换为img
    Mp4 to Img
    Python_02 基本数据类型、while循环
    Python_01 执行方式、解释器路径、编码、变量、条件语句
    数字货币,新时代货币革命的起点?
    企业区块链项目中需要避免的常见错误
    2021 年五大物联网 (IoT) 趋势
    揭开AI、机器学习和深度学习的神秘面纱
    物联网的安全性与法规的未来
    为什么分布式云是下一代云计算?Gartner分析师这样解释
  • 原文地址:https://www.cnblogs.com/knowledgesea/p/3912370.html
Copyright © 2011-2022 走看看