【设计模式】——行为型(一)

观察者模式(Observer)

定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主体对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们自己能够自动更新自己。

解释:我们都知道解决一个问题有N种解决方式,但在面向对象的设计中如何能做到“高内聚,低耦合”,设计可重用的对象才是我们追求的。在设计过程中,我们经常会接触到一种情况:一个对象的行为引发其它多个对象相应的行为。这时我们便可以通过观察者模式的设计思想来设计对象模型。

猫叫了--->老鼠跑了,主人醒了

interface ISubject   
    {   
        void Notify();//主题变动时,通知所有观察者   
        void Regiester(IObservable o);//观察者注册   
        void UnRegiester(IObservable o);//观察者取消注册,此时主题发生任何变动,观察者都不会得到通知。   
    } 
//Subject类
class Cat : ISubject   
   {   
       private IList<IObservable> observers = new List<IObservable>();   
       public void Notify()   
       {   
           foreach (IObservable o in observers) //逐个通知观察者   
           {   
               o.Action();   
           }   
       }   
       public void Regiester(IObservable o)   
       {   
           if (o != null || !observers.Contains(o))   
           {   
               observers.Add(o);   
           }   
       }   
       public void UnRegiester(IObservable o)   
       {   
           if (observers != null && observers.Contains(o))   
           {   
               observers.Remove(o);   
           }   
       }   
       public void Cry()   
       {   
           Console.WriteLine("猫叫了!");   
           Notify();   
       }   
   } 
interface IObservable   
{   
    void Action();//观察者对主题变动所对应的操作   
} 
//Observer类
class Mouse : IObservable   
   {   
       public void Action()   
       {   
           Console.WriteLine("鼠跑了!");   
       }   
   }   
   class Master : IObservable   
   {   
       public void Action()   
       {   
           Console.WriteLine("主人醒了!");   
       }   
   } 
//客户端
           Mouse mouse = new Mouse();   
           Master master = new Master();   
           Cat cat = new Cat();   
           cat.Regiester(mouse);   
           cat.Regiester(master);   
           cat.Cry();   
           Console.ReadLine(); 

—————————————————————————————————————————————————————

模板方法模式(TemplateMethod)

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

解释:在我们的现实生活中有很多例子可以拿来说明这个模式,就拿吃饺子这个事情来说,要想吃到饺子必须经过三步,第一步是“和面”,第二步是“包馅”,第三步是“煮饺子”,这三步就是一个算法,我们要想吃到不同的面和馅的饺子,对这三步中的任意一步就行操作就可以,也可以完全定义这三步,下面我们就来看看这个模式的详细介绍吧。


//客户端
            //现在想吃绿色面的,猪肉大葱馅的饺子
            AbstractClass fan = new ConcreteClass();
            fan.EatDumplings();

            Console.WriteLine();
            //过了段时间,我开始想吃橙色面的,韭菜鸡蛋馅的饺子
            fan = new ConcreteClass2();
            fan.EatDumplings();

            Console.Read();
//抽象类
    //该类型就是抽象类角色--AbstractClass,定义做饺子的算法骨架,这里有三步骤,当然也可以有多个步骤,根据实际需要而定
    public abstract class AbstractClass
    {
        //该方法就是模板方法,方法里面包含了做饺子的算法步骤,模板方法可以返回结果,也可以是void类型,视具体情况而定
        public void EatDumplings()
        {
            //和面
            MakingDough();
            //包馅
            MakeDumplings();
            //煮饺子
            BoiledDumplings();

            Console.WriteLine("饺子真好吃!");
        }

        //要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
        public abstract void MakingDough();

        //要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
        public abstract void MakeDumplings();

        //要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
        public abstract void BoiledDumplings();
    }

//具体类
    //该类型是具体类角色--ConcreteClass1,我想吃绿色面皮,猪肉大葱馅的饺子
    public sealed class ConcreteClass1 : AbstractClass
    {
        //要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
        public override void MakingDough()
        {
            //我想要面是绿色的,绿色健康嘛,就可以在此步定制了
            Console.WriteLine("在和面的时候加入芹菜汁,和好的面就是绿色的");
        }

        //要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
        public override void MakeDumplings()
        {
            //我想吃猪肉大葱馅的,在此步就可以定制了
            Console.WriteLine("农家猪肉和农家大葱,制作成馅");
        }

        //要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
        public override void BoiledDumplings()
        {
            //我想吃大铁锅煮的饺子,有家的味道,在此步就可以定制了
            Console.WriteLine("用我家的大铁锅和大木材煮饺子");
        }
    }

    //该类型是具体类角色--ConcreteClass2,我想吃橙色面皮,韭菜鸡蛋馅的饺子
    public sealed class ConcreteClass2 : AbstractClass
    {
        //要想吃饺子第一步肯定是“和面”---该方法相当于算法中的某一步
        public override void MakingDough()
        {
            //我想要面是橙色的,加入胡萝卜汁就可以。在此步定制就可以了。
            Console.WriteLine("在和面的时候加入胡萝卜汁,和好的面就是橙色的");
        }

        //要想吃饺子第二部是“包饺子”---该方法相当于算法中的某一步
        public override void MakeDumplings()
        {
            //我想吃韭菜鸡蛋馅的,在此步就可以定制了
            Console.WriteLine("农家鸡蛋和农家韭菜,制作成馅");
        }

        //要想吃饺子第三部是“煮饺子”---该方法相当于算法中的某一步
        public override void BoiledDumplings()
        {
            //此处没要求
            Console.WriteLine("可以用一般煤气和不粘锅煮就可以");
        }
    }
} 

—————————————————————————————————————————————————————

命令模式(Command)

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

解释:命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。


//客户端
            //开店前准备
            Barbecuer boy = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
            Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
            Waiter girl = new Waiter();

            //开门营业 顾客点菜
            girl.SetOrder(bakeMuttonCommand1);
            girl.SetOrder(bakeMuttonCommand2);
            girl.SetOrder(bakeChickenWingCommand1);

            //点菜完毕,通知厨房
            girl.Notify();

            Console.Read();
//抽象命令
    public abstract class Command
    {
        protected Barbecuer receiver;
        public Command(Barbecuer receiver)
        {
            this.receiver = receiver;
        }
        //执行命令
        abstract public void ExcuteCommand();
    }
//具体命令类   
    //烤羊肉串命令
    class BakeMuttonCommand : Command
    {
        public BakeMuttonCommand(Barbecuer receiver)
            : base(receiver)
        { }
        public override void ExcuteCommand()
        {
            receiver.BakeMutton();
        }
    }
    //烤鸡翅命令
    class BakeChickenWingCommand : Command
    {
        public BakeChickenWingCommand(Barbecuer receiver)
            : base(receiver)
        { }
        public override void ExcuteCommand()
        {
            receiver.BakeChickenWing();
        }
    }

//Involer请求者角色
    //服务员
    public class Waiter
    {
        private List<Command>orders=new List<Command>();//增加存放具体命令的容器
        //设置订单
        public void SetOrder(Command command)
        {
            if (command.ToString() == "_23命令模式__烧烤.BakeChickenWingCommand")
            {
                Console.WriteLine("服务员:没有鸡翅了,请点别的");
            }
            else
            {
                orders.Add(command);
                Console.WriteLine("增加订单:" + command.ToString() + "时间:" + DateTime.Now.ToString());
            }           
        }
        //取消订单
        public void CancelOrder(Command command)
        {
            orders.Remove(command);
            Console.WriteLine("取消订单:" + command.ToString() + "时间:" + DateTime.Now.ToString());
        }
        //通知全部执行
        public void Notify()
        {
            foreach (Command cmd in orders)
            {
                cmd.ExcuteCommand();
            }
        }
    }
//Receiver接收者角色
    //烤肉串者类
    public class Barbecuer
    { 
        //烤羊肉
        public void BakeMutton()
        {
            Console.WriteLine("烤羊肉串");
        }
        //烤鸡翅
        public void BakeChickenWing()
        {
            Console.WriteLine("烤鸡翅");
        }
    }
}

—————————————————————————————————————————————————————

状态模式(State)

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

解释:每个对象都有其对应的状态,而每个状态又对应一些相应的行为,如果某个对象有多个状态时,那么就会对应很多的行为。那么对这些状态的判断和根据状态完成的行为,就会导致多重条件语句,并且如果添加一种新的状态时,需要更改之前现有的代码。这样的设计显然违背了开闭原则。状态模式正是用来解决这样的问题的。状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化不再依赖于对象内部的行为。


// 电灯类,对应模式中的Context类
public class Light
{
 private LightState state;
 
 public Light(LightState state)
 {
  this.state = state;
 }
 
 // 按下电灯开关
 public void PressSwich()
 {
  state.PressSwich(this);
 }
 
 public LightState State
 {
  get { return state; }
  set { state = value; }
 } 
}
 
// 抽象的电灯状态类,相当于State类
public abstract class LightState
{
 public abstract void PressSwich(Light light);
}
 
// 具体状态类, 开
public class On : LightState
{
 /// <summary>
 /// 在开状态下,按下开关则切换到关的状态。
 /// </summary>
 /// <param name="light"></param>
 public override void PressSwich(Light light)
 {
  Console.WriteLine("Turn off the light.");
 
  light.State = new Off();
 }
}
 
// 具体状态类,关
public class Off: LightState
{

 // 在关状态下,按下开关则打开电灯。
 // <param name="light"></param>
 public override void PressSwich(Light light)
 {
  Console.WriteLine("Turn on the light.");
 
  light.State = new On();
 }
}
 
//客户端
  // 初始化电灯,原始状态为关
  Light light = new Light(new Off());
 
  // 第一次按下开关,打开电灯
  light.PressSwich();
  // 第二次按下开关,关闭电灯
  light.PressSwich();
 
  Console.Read();

—————————————————————————————————————————————————————

职责链模式(Chain of Responsibility)

使多个对象都有机会处理请求,这样系统的更改可以在不影响客户端的情况下动态的重新组织和分配责任。

解释:从生活中的例子可以发现,某个请求可能需要几个人的审批,即使技术经理审批完了,还需要上一级的审批。这样的例子,还有公司中的请假,少于3天的,直属Leader就可以批准,3天到7天之内就需要项目经理批准,多余7天的就需要技术总监的批准了。


//客户端
            CommonManager jinli = new CommonManager("金利");
            Majordomo zongjian = new Majordomo("宗件");
            GeneralManager zongjingli = new GeneralManager("钟经历");
            jinli.SetSuperior(zongjian);//设置上级
            zongjian.SetSuperior(zongjingli);

            Request request = new Request();
            request.RequestType = "请假";
            request.RequestContent = "小菜请求请假";
            request.Number = 1;
            jinli.RequestApplications(request);

            Request request2 = new Request();
            request2.RequestType = "请假";
            request2.RequestContent = "小菜请假";
            request2.Number = 4;
            jinli.RequestApplications(request2);

            Request request3 = new Request();
            request3.RequestType = "加薪";
            request3.RequestContent = "小菜请求加薪";
            request3.Number = 500;
            jinli.RequestApplications(request3);

            Request request4 = new Request();
            request4.RequestType = "加薪";
            request4.RequestContent = "小菜请求加薪";
            request4.Number = 1000;
            jinli.RequestApplications(request4);

            Console.Read();
    //申请
    class Request
    { 
        //申请类别
        private string requestType;
        public string RequestType 
        {
            get { return requestType; }
            set { requestType = value; }
        }
        //申请内容
        private string requestContent;
        public string RequestContent
        {
            get { return requestContent; }
            set { requestContent = value; }
        }
        //数量
        private int number;
        public int Number
        {
            get { return number; }
            set { number = value; }
        }
    }
    //管理者
    abstract class Manager
    {
        protected string name;
        //管理者的上级
        public Manager superior;
        public Manager(string name)
        {
            this.name = name;
        }
        //设置管理者的上级
        public void SetSuperior(Manager superior)
        {
            this.superior = superior;
        }
        //申请请求
        abstract public void RequestApplications(Request request);       
    }
    //经理
    class CommonManager : Manager
    {
        public CommonManager(string name)
            : base(name)
        { }
        public override void RequestApplications(Request request)
        {
            if (request.RequestType== "请假" && request.Number <= 2)
            {
                Console.WriteLine("{0}:{1}数量{2}被批准", name, request.RequestContent, request.Number);
            }
            else
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    //总监
    class Majordomo : Manager
    {
        public Majordomo(string name)
            : base(name)
        { }
        public override void RequestApplications(Request request)
        {
            if (request.RequestType == "请假" && request.Number <= 5)
            {
                Console.WriteLine("{0}:{1}数量{2}被批准", name, request.RequestContent, request.Number);
            }
            else
            {
                if (superior != null)
                {
                    superior.RequestApplications(request);
                }
            }
        }
    }
    //总经理
    class GeneralManager : Manager
    {
        public GeneralManager(string name)
            : base(name)
        { }
        public override void RequestApplications(Request request)
        {
            if (request.RequestType == "请假")
            {
                Console.WriteLine("{0}:{1}数量{2}被批准", name, request.RequestContent, request.Number);
            }
            else if (request.RequestType =="加薪" && request.Number <= 500)
            {
                Console.WriteLine("{0}:{1}数量{2}被批准", name, request.RequestContent, request.Number);
            }
            else if (request.RequestType == "加薪" && request.Number > 500)
            {
                Console.WriteLine("{0}:{1}数量{2}再说把", name, request.RequestContent, request.Number);
            }
        }
    }


}

猜你喜欢

转载自blog.csdn.net/mirabellezwh/article/details/80874659