最近工作不是很多,正好抽出时间学习一下期待已经的设计模式,作为一名刚毕业一年的开发人员更应该多抽出些时间了解一下设计模式。

    此片文章对策略模式做一个总结,希望对大家有帮助。

    (题外话:策略模式之前只是看定义和一些简单的例子,根本不明白,最后一头雾水,不过下面这个小例子还挺有趣的哦,能很好的理解到底什么是策略模式。)


    一.案例

    设计一个动作冒险类游戏,游戏大概是这样的:游戏中有不同的角色,每个角色战斗时使用的武器不同。现有两个角色:骑士(Knight)和巨魔头(Troll),Knight的武器是宝剑(Sword),巨魔头的武器是斧头(Axe);作战规则,先确定身份,使用武器作战,最后停止作战。


    1.分析:

       Knight和Troll都是角色,所以可以定义一个超类Character;

       确定角色身份,使用武器,作战,停止作战都作为Character类具有的方法:

       (1)每个角色的身份,使用武器作战的方式不同,所以在Character中定义为抽象方法(abstract),在子类Knight和Troll中具体实现;

       (2)而停止作战就是一个停止动作,所以直接在character中实现由子类继承即可。


    2.按照如上分析代码实现(体现了基本的OO设计原则:继承、抽象)

         角色类(超类):

    public abstract class Character {    
    
        public abstract void identify();
        
        public abstract void fight();
        
        public void stopFight(){
            System.out.println("Hi,stop fight and go to sleep,now");
        }
    }

        骑士类(子类):

    public class Knight extends Character{

        //实现父类的接口
        public void identify() {
            System.out.println("Hi,everybody,I am a handsome Knight");
        }
    
        //实现父类的接口
        public void fight() {
            System.out.println("I fight with Sword the King give me");
        }

    }

        巨魔头类(子类):

    public class Troll extends Character{    
    
        public void identify() {
            System.out.println("I am a Troll,I want to control the entire universe");
        }
    
        public void fight() {
            System.out.println("My axe never relented");
        }
    
    }

    3.总结:

       此时的程序设计已经满足了OO设计中的继承和抽象原则,但是设想一下,如果后期需要添加更过的角色,每个角色使用的武器都不相同,或者需要更改原来的角色使用的武器;设置要求某些角色可以在运行中更换武器,这样,程序的维护性就增加了困难。


    4.重新分析:

       对于每个角色来说,使用不同的武器来作战属于一种行为,以上设计实现的方式是角色类自己去执行自己的行为,这样导致,多种角色时,代码冗余不好控制,没有独立性。

       不如我们把变化的行为拿出来单独封装在指定的类中,以接口的形式定义,在每个角色类中实现并处理执行相应的行为。这样可以使得后期变化的东西不会改变其他不变的。


    5.按照如上分析,给出整理代码(体现了OO设计中的封装和多态):


      角色类(超类):

    public abstract class Character {    
        //使用WeaponBehavior类
        protected WeaponBehavior weaponBehavior;
    
        //构造方法
        public Character(){
            
        }
        
        //定义fight方法,委托WeaponBehavior类对象做对应的事情
        public void fight(){
            weaponBehavior.useWeanpon();
        }
        
        //抽象方法,子类实现
        public abstract void identify();
        
        //父类方法,子类直接使用
        public void stopFight(){
            System.out.println("Hi,stop fight and go to sleep,now");
        }
    
        //设置方式,可以在运行过程中更改某个角色的使用武器
        public void setWeaponBehavior(WeaponBehavior weaponBehavior) {
            this.weaponBehavior = weaponBehavior;
        }
    }

     子类--骑士类:

    public class Knight extends Character{    
        
        //构造方法,创建使用的武器对象
        public Knight(){
            //骑士使用的是宝剑
            weaponBehavior = new Sword();
        }
    
        //实现父类的接口
        public void identify() {
            System.out.println("Hi,everybody,I am a handsome Knight");
        }
    
    }

    子类--巨魔头类:

    public class Troll extends Character{    
        
        //构造方法,创建使用的武器对象
        public Troll(){
            //巨魔头使用的是宝斧头
            weaponBehavior = new Axe();
        }
    
        public void identify() {
            System.out.println("I am a Troll,I want to control the entire universe");
        }
    
    }

    分离出的行为定义的抽象类:

    public interface WeaponBehavior {    
        public void useWeanpon();
    }

    行为抽象类的实现类之一--使用宝剑的实现类:

    public class Sword  implements WeaponBehavior{    
    
        public void useWeanpon() {
            System.out.println("Sword");
        }
    }

    行为抽象类的实现类之二--使用斧头的实现类:

    public class Axe  implements WeaponBehavior{    
    
        public void useWeanpon() {
            System.out.println("Axe");        
        }
    }

    行为抽象类的实现类之三--新增的弓箭实现类:

    public class BowAndArrow implements WeaponBehavior{    
    
        public void useWeanpon() {
            System.out.println("Bow and Arrow");        
        }
    
    }

    主方法调用测试:

        //创建角色对象--多态
        Character king = new King();
        king.identify();
        //委托
        king.fight();
        king.stopFight();
        
        //创建角色对象--多态
        Character knight = new Knight();
        knight.identify();
        //委托
        knight.fight();
        knight.stopFight();
        //改变行为
        knight.setWeaponBehavior(new BowAndArrow());
        knight.fight();
        knight.stopFight();

    执行结果:

    国王:        
        I am the king of all
        Sword
        Hi,stop fight and go to sleep,now
        
    骑士:
        Hi,everybody,I am a handsome Knight
        Sword
        Hi,stop fight and go to sleep,now
        Bow and Arrow
        Hi,stop fight and go to sleep,now


二.关于观察者模式结合例子的总结

    1.每一个角色都有一个WeaponBehavior并委托他们做使用不同武器作战行为--其实这
       就是UML中的组合(composition)关系,即将两个结合起来使用。
    2.角色的行为被封装到一组类中,并可以被轻易额扩充和改变,甚至可以在运行时改变行为。
    3.体现的OO的封装(可变的一组行为的封装成类)、抽象、继承、多态;


三.例子中体现的OO设计中一些设计原则

    设计原则:
    1.封装变化:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起;
    (1)把会变化的部分“封装”起来,好让其他不需要变化的部分不会收到变化部分的影响;
    (2)好处:使得由于代码变化导致的不经意后果变少,系统变得更加有弹性;
    2.针对接口编程,不针对实现编程
    (1)针对接口编程真正的意思是,针对超类型(supertype)编程;
    (2)关键点:利用多态
    (3)某个类将一些可变的行为动作“委托(delegate)”别的类处理,而非定义在本类或子类中。
    3.多用组合,少用继承
    (1)使用组合优点:使系统有更大的弹性,不仅可以将算法族(一组行为)封装成类,并且可以
         做到在运行时动态额改变行为(算法);


四.本文重点--策略模式的定义:

    **第一个设计模式:策略模式(Strategy pattern)
    正式定义:
    策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

    
    学习设计模式的优势:
    1.可以使你思考架构的层次提高到模式层次,而不仅仅停留在琐碎的对象上。
    2.模式能够让你用更少的词汇做更充分的沟通;
    3.要想建立可维护的OO系统,要诀就在于随时想到系统系统以后可能需要的变化以及应付变化的原则。