最近去图书馆借到了一本好书《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),将以上两种情况封装成接口,只要那个兵种需要这种功能,就可以通过实现接口来达到自己的目的 以下是改进之后的代码:- //士兵抽象类
- public abstract class Soldier {
- WeaponBehavior weaponBehavior ;
- FlyBehavior flyBehavior ;
- public float lifeValue ;//每个兵种的生命值和护甲都一样
- public int armor ;
- public abstract void disPlay ();//每个兵种的外表都不一样
- public void showWeaponAction (){
- weaponBehavior.fight ();
- }
- public void showFlyAction (){
- flyBehavior.fly ();
- }
- }
- //攻击方式接口
- public interface WeaponBehavior {
- public void fight ();
- }
- //长刀武器实现接口
- public class KnifeBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用长刀攻击敌人");
- }
- }
- //弓箭攻击方式实现接口
- public class ArrowBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用弓箭攻击敌人");
- }
- }
- //大炮攻击方式实现接口
- public class CannonBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用大炮攻击敌人");
- }
- }
- //手枪攻击方式实现接口
- public class GunBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用手枪攻击敌人");
- }
- }
- //放火攻击方式实现接口
- public class FireBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用放火攻击敌人");
- }
- }
- public class WaterOgreBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用召唤水怪攻击敌人");
- }
- }
- public class WaterOgreBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用暴风雪攻击敌人");
- }
- }
- public class AbsorbMagicBehavior implements WeaponBehavior {
- public void fight (){
- System.out.println ("用吸收魔法攻击敌人");
- }
- }
- //创建飞行动作接口
- public interface FlyBehavior {
- public void fly ();
- }
- public class FlyWithWings implements FlyBehavior{
- public void fly (){
- System.out.println ("I'm flying");//用翅膀飞翔
- }
- }
- public class FlywithRocketPower implements FlyBehavior{
- public void fly (){
- System.out.println ("I'm flying");//用火箭翱翔
- }
- }
- //步兵A类
- public class FootManA extends Soldier {
- public FootManA (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new KnifeBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是步兵A");
- }
- }
- //步兵B类
- public class FootManB extends Soldier {
- public FootManB (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new ArrowBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是步兵B");
- }
- }
- //炮兵类A
- public class ArtilleryManA extends Soldier {
- public ArtilleryManA (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new GunBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是炮兵A");
- }
- }
- //炮兵类B
- public class ArtilleryManB extends Soldier {
- public ArtilleryManB (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new CannonBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是炮兵B");
- }
- }
- //血法师类
- public class BloodMageHero extends Soldier {
- public BloodMageHero (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new FireBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是血法师");
- }
- }
- //魔法师类
- public class MagicianHero extends Soldier {
- public MagicianHero (float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new WaterOgreBehavior ();
- }
- public void disPlay (){
- System.out.println ("我是魔法师");
- }
- }
- public class Bird extends Soldier {
- public Bird(float lifeValue, int armor){
- super.lifeValue = lifeValue;
- super.armor = armor ;
- weaponBehavior = new ArrowBehavior ();
- flyBehavior = new FlyWithWings ();
- }
- public void disPlay (){
- System.out.println ("我是飞兽");
- }
- }
- //生产军队
- public class ProduceArmy {
- public static void main (String[] args){
- Soldier footManA = new FootManA (100.0f,20);//生产步兵A
- footManA.disPlay ();
- footManA.showWeaponAction ();
- Soldier footManB = new FootManB (100.0f,20);//生产步兵B
- footManB.disPlay ();
- footManB.showWeaponAction ();
- Soldier artilleryManA = new ArtilleryManA (200.0f,50);//生产炮兵A
- artilleryManA.disPlay ();
- artilleryManA.showWeaponAction ();
- Soldier artilleryManB = new ArtilleryManB (200.0f,50);//生产炮兵B
- artilleryManB.disPlay ();
- artilleryManB.showWeaponAction ();
- Soldier magicianHero = new MagicianHero (1000.0f,150);//生产魔法师
- magicianHero.disPlay ();
- magicianHero.showWeaponAction ();
- Soldier bloodMageHero = new BloodMageHero (1000.0f,150);//生产血法师
- bloodMageHero.disPlay ();
- bloodMageHero.showWeaponAction ();
- Soldier bird = new Bird (500,150);//生产飞兽
- bird.disPlay ();
- bird.showWeaponAction ();
- }
- }
代码有点多!⊙﹏⊙b汗
虽然程序中有些还是写的不太好,下次写的时候可能就会去改进这些不足的地方了~!