.NET常用设计模式(二)

>> strategy(策略模式)

1. 概述
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以互相替换。策略模式让算法独立于使用它的客户而独立变化
2. 适用性
1) 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种
2) 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
3) 算法使用客户不应该知道的数据。可以使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4) 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的strategy类中以代替这些条件语句。
3. 结构
 
4. 实例
#region 封装 UseWeapon() 行为
      /// <summary>
      /// 定义使用 武器接口
      /// </summary>
      public interface IWeaponable
      {
            void UseWeapon();
      }
      // 使用 剑 的类
      public class UseSword : IWeaponable
      {
            public void UseWeapon()
            {
                  Console.WriteLine("Action: Sword Armed. There is a sharp sword in my hands now.");
            }
      }
      // 使用 斧 的类
      public class UseAxe : IWeaponable
      {
            public void UseWeapon()
            {
                  Console.WriteLine("Action: Axe Armed. There is a heavy axe in my hands now.");
            }
      }
      // 不能使用武器的类
      public class UseNothing : IWeaponable
      {
            public void UseWeapon()
            {
                  Console.WriteLine("Speak: I can't use any weapon.");
            }
      }
      #endregion
      #region 定义角色类
      /// <summary>
      /// 角色基类
      /// </summary>
      public abstract class Character
      {

            protected IWeaponable WeaponBehavior; // 通过此接口调用实际的 UseWeapon方法。
            // 使用武器,通过接口来调用方法
            public void UseWeapon()
            {
                  WeaponBehavior.UseWeapon();
            }
            // 动态地给角色更换武器
            public void ChangeWeapon(IWeaponable newWeapon)
            {
                  Console.WriteLine("Haha, I've got a new equip.");
                  WeaponBehavior = newWeapon;
            }
            public void Walk()
            {
                  Console.WriteLine("I'm start to walk ...");
            }
            public void Stop()
            {
                  Console.WriteLine("I'm stopped.");
            }
            public abstract void DisplayInfo(); // 显示角色信息
      }
      // 定义野蛮人
      public class Barbarian : Character
      {
            public Barbarian()
            {
                  // 初始化继承自基类的WeaponBehavior变量
                  WeaponBehavior = new UseAxe();  // 野蛮人用斧
            }
            public override void DisplayInfo()
            {
                  Console.WriteLine("Display: I'm a Barbarian from northeast.");
            }
      }
      // 定义圣骑士
      public class Paladin : Character
      {
            public Paladin()
            {
                  WeaponBehavior = new UseSword();
            }
            public override void DisplayInfo()
            {
                  Console.WriteLine("Display: I'm a paladin ready to sacrifice.");
            }
      }
      // 定义法师
      public class Wizard : Character
      {
            public Wizard()
            {
                  WeaponBehavior = new UseNothing();
            }
            public override void DisplayInfo()
            {
                  Console.WriteLine("Display: I'm a Wizard using powerful magic.");
            }
      }
      #endregion
      // 测试程序
      class Program
      {
            static void Main(string[] args)
            {
                  Character barbarian = new Barbarian(); // 默认情况下野蛮人用斧
                  barbarian.DisplayInfo();
                  barbarian.Walk();
                  barbarian.Stop();
                  barbarian.UseWeapon();
                  barbarian.ChangeWeapon(new UseSword());   // 现在也可以使用剑
                  barbarian.UseWeapon();
                  barbarian.ChangeWeapon(new UseNothing());// 也可以让他什么都用不了,当然一不会这样:
                  barbarian.UseWeapon();
                  Console.ReadKey();
            }
      }

>> memento(备忘录模式)

1. 概述
Memento模式也叫备忘录模式,它的作用是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,在需要的时候(undo/rollback)恢复对象以前的状态
2. 适用性
必须保存一个对象在某一时刻(部分)状态,这样以后需要时它才能恢复到先前的状态。如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
3. 结构
 
4. 实例分析
public class OurObjectMemento
      {
            int internalState;
            string anotherState;

            public int InternalState
            {
                  get
                  {
                        return internalState;
                  }
            }
            public string AnotherState
            {
                  get
                  {
                        return anotherState;
                  }
            }
            public OurObjectMemento(int internalState, string anotherState)
            {
                  this.internalState = internalState;
                  this.anotherState = anotherState;
            }
      }
      public class OurObject
      {
            int internalState = 0;
            string anotherState = "I know nothing";
            public OurObjectMemento CreateMemento()
            {
                  return new OurObjectMemento(internalState, anotherState);
            }
            public void ReStoreMemento(OurObjectMemento memento)
            {
                  this.internalState = memento.InternalState;
                  this.anotherState = memento.AnotherState;
            }
            public void DoStuff()
            {
                  internalState = 42;
                  anotherState = "I know the question too";
            }
            public void PrintState()
            {
                  Console.WriteLine("current state is {0}:{1}", internalState, anotherState);
            }
      }
由上可知,memento自身公开了所有OurObject内部变量。在SharpDevelop中,所有memento都可将自身转换为XML(并可返回),从而保持了对象状态的连续性

>> proxy(代理模式)

1. 意图
为其他对象提供一种代理以控制这个对象的访问
2. 概述
在软件系统中,有些对象有时候由于跨越网络或者其它的障碍,而不能够或者不想直接访问另一个对象,如果直接访问会给系统带来不必要的复杂性,这时候可以在客户程序和目标对象之间增加一层中间层,让代理对象来代替目标对象打点一切。
3. 结构图
 
4. 实例分析
/// <summary>
      /// 代理接口,保证client&server都实现相应方法
      /// </summary>
      public interface IMath
      {
            double Add(double x, double y);

            double Sub(double x, double y);

            double Mul(double x, double y);

            double Dev(double x, double y);
      }

      /// <summary>
      /// 服务器端方法
      /// </summary>
      public class Math : IMath
      {
            public double Add(double x, double y)
            {
                  return x + y;
            }

            public double Sub(double x, double y)
            {
                  return x - y;
            }

            public double Mul(double x, double y)
            {
                  return x * y;
            }

            public double Dev(double x, double y)
            {
                  return x / y;
            }
      }

      /// <summary>
      /// 代理方法
      /// </summary>
      public class MathProxy : IMath
      {
            Math math = new Math();
            public double Add(double x, double y)
            {
                  return math.Add(x, y);
            }

            public double Sub(double x, double y)
            {
                  return math.Sub(x, y);
            }

            public double Mul(double x, double y)
            {
                  return math.Mul(x, y);
            }

            public double Dev(double x, double y)
            {
                  return math.Dev(x, y);
            }
      }
      /// <summary>
      /// 主程序
      /// </summary>
      public class App
      {
            public static void Main()
            {
                  MathProxy proxy = new MathProxy();
                  double addresult = proxy.Add(2, 3);
                  double subresult = proxy.Sub(2, 3);
                  double mulresult = proxy.Mul(2, 3);
                  double devresult = proxy.Dev(2, 3);
            }
      }
分析:实例中无非在客户端和Math类之间增加了一个间接层,这也是我们比较常见的解决问题的手段之一。另外,对于程序中的接口Imath,并不是必须的,大多数情况下,我们为了保持对象操作的透明性,并强制实现类、代理类所要调用的所有的方法,我们会让他们实现同一个接口。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值