首页 > 代码库 > 设计模式-单例模式,观察者模式

设计模式-单例模式,观察者模式

序言

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

观察者模式

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

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

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

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

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

   //炸弹    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 += "\n";            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#设计模式