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

序言

点击查看:设计模式系列

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

观察者模式

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

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

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

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

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

   //炸弹
    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#设计模式

posted @ 2014-08-15 12:18  张龙豪  阅读(7702)  评论(8编辑  收藏  举报