《head first 设计模式》之策略模式

时间:2021-06-18 21:56:54

最近去图书馆借到了一本好书《head first 设计模式》,是介绍Java设计模式。这本书生动的传授方式相信大部分初级读者是非常喜欢的,没有晦涩难懂的概念,但是用简洁的话来表达设计模式的核心思想。

          这几天集中领悟设计模式中的策略模式---就是把一些容易变化的部分抽出来,新建一个接口来封装这些特性,以便以后维护和代码复用。           事不宜迟,现在和大家分享一下自己学的东西。           现在我们设计一个魔兽人族的游戏:           第一,我们先来分析一下:           first  step 人族有好几种兵种:          步兵(FootMan),假如步兵有几种攻击方式,有弓箭(Arrow),长刀(knife)。          炮兵(ArtilleryMan),攻击方式,有火枪(gun),也有大炮(cannon)。          有两个英雄(Hero),第一个英雄攻击方式Skills,有放火(Fire),吸魔法(AbsorbMagic);第二个英雄有:下雪(Snow),放出水元素(WaterOgre);     PS:为了简化分析模式,所以很多技能和兵种都省略了。          second step 现在以我们一般的OOP思想来设计类:       one:士兵类(Soldier)【步兵、炮兵、英雄可以设为子类,因为都属于兵种,所以可以从Soldier中继承。】该类中包括属性:生命值( lifeValue),护甲(Armor)【只有英雄有物品属性(goodValue),魔法值,经验值,级别;这些可在英雄子类中添加】           因此可以写代码了(为了分析方便,在这里,全部的属性都是public): Code: 1.       //士兵抽象类  2.       public abstract class Soldier {   3.           public float lifeValue ;//每个兵种的生命值和护甲都一样  4.           public int armor ;   5.           public abstract void disPlay ();//每个兵种的外表都不一样  6.       }   Code: 1.       //步兵类  2.       public class FootMan extends Soldier {   3.            public FootMan (float lifeValue, int armor){   4.                super.lifeValue = lifeValue;   5.                super.armor = armor ;   6.            }   7.            public void arrowFight (){   8.                System.out.println ("用弓箭攻击!");   9.            }   10.        public void knifeFight (){   11.            System.out.println ("用长刀攻击!");   12.        }   13.        public void disPlay (){   14.            System.out.println ("我是步兵!");   15.        }   16.   }   Code: 1.       //炮兵类  2.       public class ArtilleryMan extends Soldier {   3.            public ArtilleryMan (float lifeValue, int armor){   //利用构造函数为属性赋值4.                super.lifeValue = lifeValue;   5.                super.armor = armor ;   6.            }   7.            public void GunFight (){   8.                System.out.println ("用手枪攻击!");   9.            }   10.        public void CannonFight (){   11.            System.out.println ("用大炮攻击!");   12.        }   13.        public void disPlay (){   14.            System.out.println ("我是炮兵!");   15.        }   16.   }    Code: 1.       //英雄抽象类  2.       public abstract class Hero extends Soldier {   //继承抽象类,添加抽象方法3.            public abstract void skill ();       4.       }    Code: 1.       //血法师类  2.       public class BloodMageHero extends Hero {   3.           public BloodMageHero (float lifeValue, int armor){   4.               super.lifeValue = lifeValue;   5.               super.armor = armor ;   6.           }   7.           public void skill (){   8.              System.out.println ("我会放火和吸魔法");   9.           }   10.       public void disPlay (){   11.          System.out.println ("我是血法师");   12.       }   13.   }    Code: 1.       //魔法师类  2.       public class MagicianHero extends Hero {   3.         4.           public MagicianHero (float lifeValue, int armor){   5.               super.lifeValue = lifeValue;   6.               super.armor = armor ;   7.           }   8.           public void skill (){   9.              System.out.println ("我会产生水元素和下雪");   10.       }   11.       public void disPlay (){   12.          System.out.println ("我是魔法师");   13.       }   14.   }    Code: 1.       //主类,士兵测试类  2.       public class SoldierDemo {   3.           public static void main (String[] args){   4.         5.               FootMan footMan = new FootMan (100,20);//产生一个步兵  6.               footMan.disPlay ();   7.               footMan.arrowFight ();//使用弓箭攻击  8.         9.               ArtilleryMan artilleryMan = new ArtilleryMan (200,30);   10.           artilleryMan.CannonFight ();   11.           artilleryMan.disPlay ();   12.              13.           MagicianHero magicianHero = new MagicianHero (500,100);   14.           magicianHero.skill ();   15.           magicianHero.disPlay ();   16.     17.           BloodMageHero bloodMageHero = new BloodMageHero (500,100);   18.           bloodMageHero.skill ();   19.           bloodMageHero.disPlay ();   20.     21.       }   22.   }   这个是用OOP思想设计的程序,可能大家看起来没有任何问题,因为程序已经按照面向对象的思想去编写了。 那么好了,但是问题也来了:如果现在要升级我们的游戏,增加我们的兵种,现在我们可以生产可以飞的兵种(fly),大家可能立刻想:这个很简单啊,不就是往士兵类加多一个飞的方法吗?!楼主,写这个文章,你多此一举了。 嗯,可能答案并不是你所想的!因为,添加飞的动作可能影响到所有的兵种,包括步兵(是不是很可笑,步兵也可以飞),可能也有人说我们可以覆盖了Soldier父类中的fly()方法而什么都不做,但是这样做会增加我们的代码量和我们的工作量。 因此,我们可以利用设计模式中的策略模式进行改进,把一些变化的方法进行封装,达到代码复用,增加系统的可维护性和系统的弹性。 其中可变化的部分有士兵的攻击方式(WeaponBehavior),飞技能(FlyBehavior),将以上两种情况封装成接口,只要那个兵种需要这种功能,就可以通过实现接口来达到自己的目的 以下是改进之后的代码: Code:
  1. //士兵抽象类   
  2. public abstract class Soldier {   
  3.     WeaponBehavior weaponBehavior ;   
  4.     FlyBehavior flyBehavior ;   
  5.   
  6.     public float lifeValue ;//每个兵种的生命值和护甲都一样   
  7.     public int armor ;   
  8.   
  9.     public abstract void disPlay ();//每个兵种的外表都不一样   
  10.   
  11.     public void showWeaponAction (){   
  12.         weaponBehavior.fight ();   
  13.     }   
  14.   
  15.     public void showFlyAction (){   
  16.         flyBehavior.fly ();   
  17.     }   
  18. }   
Code:
  1. //攻击方式接口   
  2. public interface WeaponBehavior {   
  3.    public void fight ();   
  4. }  
Code:
  1. //长刀武器实现接口   
  2. public class KnifeBehavior implements WeaponBehavior {   
  3.      public void fight (){   
  4.          System.out.println ("用长刀攻击敌人");   
  5.      }   
  6. }  
Code:
  1. //弓箭攻击方式实现接口   
  2. public class ArrowBehavior implements WeaponBehavior {   
  3.      public void fight (){   
  4.          System.out.println ("用弓箭攻击敌人");   
  5.      }   
  6. }  
Code:
  1. //大炮攻击方式实现接口   
  2. public class CannonBehavior implements WeaponBehavior {   
  3.      public void fight (){   
  4.          System.out.println ("用大炮攻击敌人");   
  5.      }   
  6. }  
Code:
  1. //手枪攻击方式实现接口   
  2. public class GunBehavior implements WeaponBehavior {   
  3.      public void fight (){   
  4.          System.out.println ("用手枪攻击敌人");   
  5.      }   
  6. }  
Code:
  1. //放火攻击方式实现接口   
  2. public class FireBehavior implements WeaponBehavior {   
  3.      public void fight (){   
  4.          System.out.println ("用放火攻击敌人");   
  5.      }   
  6. }  
Code:
  1. public class WaterOgreBehavior implements WeaponBehavior {   
  2.      public void fight (){   
  3.          System.out.println ("用召唤水怪攻击敌人");   
  4.      }   
  5. }  
Code:
  1. public class WaterOgreBehavior implements WeaponBehavior {   
  2.      public void fight (){   
  3.          System.out.println ("用暴风雪攻击敌人");   
  4.      }   
  5. }  
Code:
  1. public class AbsorbMagicBehavior implements WeaponBehavior {   
  2.      public void fight (){   
  3.          System.out.println ("用吸收魔法攻击敌人");   
  4.      }   
  5. }  
  Code:
  1. //创建飞行动作接口   
  2. public interface FlyBehavior {   
  3.    public void fly ();   
  4. }  
Code:
  1. public class FlyWithWings implements FlyBehavior{   
  2.     public void fly (){   
  3.          System.out.println ("I'm flying");//用翅膀飞翔   
  4.      }   
  5. }  
Code:
  1. public class FlywithRocketPower implements FlyBehavior{   
  2.     public void fly (){   
  3.          System.out.println ("I'm flying");//用火箭翱翔   
  4.      }   
  5. }  
Code:
  1. //步兵A类   
  2. public class FootManA extends Soldier {   
  3.     public FootManA (float lifeValue, int armor){   
  4.          super.lifeValue = lifeValue;   
  5.          super.armor = armor ;   
  6.          weaponBehavior = new KnifeBehavior ();   
  7.     }   
  8.     public void disPlay (){   
  9.        System.out.println ("我是步兵A");   
  10.     }   
  11. }   
Code:
  1. //步兵B类   
  2. public class FootManB extends Soldier {   
  3.     public FootManB (float lifeValue, int armor){   
  4.          super.lifeValue = lifeValue;   
  5.          super.armor = armor ;   
  6.          weaponBehavior = new ArrowBehavior ();   
  7.     }   
  8.     public void disPlay (){   
  9.        System.out.println ("我是步兵B");   
  10.     }   
  11. }   
Code:
  1. //炮兵类A   
  2. public class ArtilleryManA extends Soldier {   
  3.      public ArtilleryManA (float lifeValue, int armor){   
  4.          super.lifeValue = lifeValue;   
  5.          super.armor = armor ;   
  6.          weaponBehavior = new GunBehavior ();   
  7.      }   
  8.     public void disPlay (){   
  9.        System.out.println ("我是炮兵A");   
  10.     }   
  11. }   
Code:
  1. //炮兵类B   
  2. public class ArtilleryManB extends Soldier {   
  3.      public ArtilleryManB (float lifeValue, int armor){   
  4.          super.lifeValue = lifeValue;   
  5.          super.armor = armor ;   
  6.          weaponBehavior = new CannonBehavior ();   
  7.      }   
  8.     public void disPlay (){   
  9.        System.out.println ("我是炮兵B");   
  10.     }   
  11. }   
Code:
  1. //血法师类   
  2. public class BloodMageHero extends Soldier {   
  3.     public BloodMageHero (float lifeValue, int armor){   
  4.         super.lifeValue = lifeValue;   
  5.         super.armor = armor ;   
  6.         weaponBehavior = new FireBehavior ();   
  7.   
  8.     }   
  9.     public void disPlay (){   
  10.        System.out.println ("我是血法师");   
  11.     }   
  12. }   
Code:
  1. //魔法师类   
  2. public class MagicianHero extends Soldier {   
  3.     public MagicianHero (float lifeValue, int armor){   
  4.         super.lifeValue = lifeValue;   
  5.         super.armor = armor ;   
  6.         weaponBehavior = new WaterOgreBehavior ();   
  7.   
  8.     }   
  9.     public void disPlay (){   
  10.        System.out.println ("我是魔法师");   
  11.     }   
  12. }   
Code:
  1. public class Bird extends Soldier {   
  2.     public Bird(float lifeValue, int armor){   
  3.          super.lifeValue = lifeValue;   
  4.          super.armor = armor ;   
  5.          weaponBehavior = new ArrowBehavior ();   
  6.          flyBehavior = new FlyWithWings ();   
  7.     }   
  8.     public void disPlay (){   
  9.          System.out.println ("我是飞兽");   
  10.     }   
  11. }  
Code:
  1. //生产军队   
  2. public class ProduceArmy {   
  3.     public static void main (String[] args){   
  4.   
  5.         Soldier footManA = new FootManA (100.0f,20);//生产步兵A   
  6.         footManA.disPlay ();   
  7.         footManA.showWeaponAction ();   
  8.   
  9.         Soldier footManB = new FootManB (100.0f,20);//生产步兵B   
  10.         footManB.disPlay ();   
  11.         footManB.showWeaponAction ();   
  12.   
  13.         Soldier artilleryManA = new ArtilleryManA (200.0f,50);//生产炮兵A   
  14.         artilleryManA.disPlay ();   
  15.         artilleryManA.showWeaponAction ();   
  16.            
  17.         Soldier artilleryManB = new ArtilleryManB (200.0f,50);//生产炮兵B   
  18.         artilleryManB.disPlay ();   
  19.         artilleryManB.showWeaponAction ();   
  20.       
  21.         Soldier magicianHero = new MagicianHero (1000.0f,150);//生产魔法师   
  22.         magicianHero.disPlay ();   
  23.         magicianHero.showWeaponAction ();   
  24.   
  25.   
  26.         Soldier bloodMageHero = new BloodMageHero (1000.0f,150);//生产血法师   
  27.         bloodMageHero.disPlay ();   
  28.         bloodMageHero.showWeaponAction ();   
  29.   
  30.   
  31.         Soldier bird = new Bird (500,150);//生产飞兽   
  32.         bird.disPlay ();   
  33.         bird.showWeaponAction ();   
  34.   
  35.     }   
  36. }  

代码有点多!⊙﹏⊙b汗

虽然程序中有些还是写的不太好,下次写的时候可能就会去改进这些不足的地方了~!