策略模式
定义了算法族,分别封装起来,让他们之间可以相互更换,此模式让算法的变化独立于利用者,使系统不在担心遇到任何改变,即动态的设定功能。
1. 问题场景
顾客或者用户必要别的东西,或者想要新的功能。功能的改进或者是添加必要我们去改动应用中的代码,我们知道偶然候利用继续并不能很好的办理问题,由于对象的举动或者说是功能在子类里不断的改变,让全部的子类都有都有这些举动或是功能是不恰当的。
2. 实例
好比说我们做一个对战游戏中会出各种的的人物,此系统内部计划利用了尺度的oo技能,计划了一个人物超类,并让各种人物继续此超类。
public abstract class Role
{
public int HP { get; set; } = 10;
public int MP { get; set; } = 10;
public void attack(Role role) {
role.HP--;
Console.WriteLine("我打了你一下 ! ! !还没有掉蓝 !!!");
}
public abstract void display();
}
public class RoleA:Role
{
public override void display()
{
Console.WriteLine("我是A");
}
}
public class RoleB : Role
{
public override void display()
{
Console.WriteLine("我是B");
}
}
忽然有一天,必要脚色会利用武器,出现物理攻击和法术攻击等一系列的打击方式,这样就有一个问题如果我修改攻击方式就会修改全部脚色的攻击方式,对代码所作的局部修改,影响的层面可不止是局部。呐,我第一时间想到就是继续我把攻击的方法覆盖掉。
public class RoleA:Role
{
public override void display()
{
Console.WriteLine("我是A");
}
new public void attack(Role role) {
role.HP--;
this.MP--;
Console.WriteLine("我打了你一下 ! ! !掉蓝了 !!!");
}
}
这样攻击代码就是不能重复,但是这样如果产物不停要更新修改攻击模式,我们就陷入了无穷无尽的修改查抄覆盖的噩梦中。我又想到如果我把这些多变的功能拿出来做成接口给让他成继续关系我是不是就可以少了查抄,但是重复的代码仍旧会变多。照旧没有办理。
继续并不能很好的办理问题,由于脚色攻击举动在子类里不断的变化,并且让全部的子类有这样的攻击举动是不正确的,创建一个攻击接口的方法好像不错,但是c#接口并不具有实现代码,所以继续接口无法到达代码的复用。这意味着我们必须往下查找在定义此举动的类中修改它。轻易造成新的错误。
这样我就想到了一个计划原则:
找出应用中可能必要的变化之处,把他们独立出来,反面不必要变化的代码混在一起
这样的代码的变化引起不经意的结果变少系统变得更有弹性。
第二个计划原则:
面向接口编程而不是面向实现编程。
这样脚色的攻击举动将被分开放在类中,此类专门提供某举动的接口,这样,脚色的类就不再必要知道举动实现的具体细节了。
说到这里就不得不说到接口了,接口是一个“概念”也是C#的interface的构造。我们可以在不涉及interface的环境下“面向接口编程”,其实“面向接口编程”就是“面向超类编程”,通常就是一个抽象或者是一个接口。关键就是利用多态,步伐就可针对超类编程,实行时就会实行带真正的举动。不会绑死在超类的举动上。
额 废话有点多,上代码:
public interface AttackBehavior
{
void attack(Role role);
}
public class PhysicalAttack : AttackBehavior
{
public void attack(Role role)
{
role.HP--;
Console.WriteLine("我打了你一下 ! ! !还没有掉蓝 !!!");
}
}
public abstract class Role
{
protected AttackBehavior attackBehavior;
public int HP { get; set; } = 10;
public int MP { get; set; } = 10;
public void attack(Role role) {
attackBehavior.attack(role);
}
public abstract void display();
}
public class RoleA:Role
{
public RoleA(AttackBehavior attack)
{
attackBehavior = attack;
}
public override void display()
{
Console.WriteLine("我是A");
}
}
- <code>这样就可以直接在main调用了
- static void Main(string[] args)
- {
- Role roleA = new RoleA();
- roleA.Attack();
- }</code>
复制代码
我们封装了举动把 “是一个” 变成 “有一个” 恰好符合了另一个计划原则:
多用组合少继续
完
d=====( ̄▽ ̄*)b
来源:https://www.cnblogs.com/MTCS/archive/2019/09/23/11575249.html |