• 设计模式——策略模式


    对设计模式的理解

    模式不是代码,而是针对设计问题的通用解决方案。你可以把它们应用到特定的应用中;设计模式告诉我们如何组织类和对象以及解决某种问题。

    想要数量使用设计模式需要对封装继承多态有一个全面的了解,熟悉常用的OO设计原则。

    使用模式最好的方式是:把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们,以往是代码复用,现在是经验复用

    策略模式

    定义:定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

    下面使用一个实际开发中的例子来分析策略模式,假如有这样一个需求,在一个动作冒险游戏中,有四个游戏角色,分别是:Queen(王后),King(国王),Troll(巨魔),Knight(骑士);每个角色都可以使用不同的武器,例如匕首,弓箭,斧头,宝剑,每个角色一次只能使用一种武器,但是可以在游戏的过程中切换武器。

      首先分析行为,角色们都可以使用武器,使用武器算是角色的一种通用的行为,所以首先定义一个WeaponBehavior武器使用接口,里面只有一个useWeapon()方法:

    public interface WeaponBehavior {
        public void useWeapon();
    }

      每一个角色都可以使用不同的武器,所以把每个武器的具体使用方式放在单独的类中,一个类就代表一种使用方式,这些类全部实现WeaponBehavior接口(这是关键的一步,我们在这里就相当于把会变化的部分同不变的部分分开了)。

    public class AxeBehavior implements WeaponBehavior {
    
        @Override
        public void useWeapon() {
            // TODO Auto-generated method stub
            System.out.println("实现用斧头劈砍!");
        }
    
    }
    public class BowAndArrowBehavior implements WeaponBehavior {
    
        @Override
        public void useWeapon() {
            // TODO Auto-generated method stub
            System.out.println("实现用弓箭射击!");
        }
    
    }
    public class KnifeBehavior implements WeaponBehavior {
    
        @Override
        public void useWeapon() {
            // TODO Auto-generated method stub
            System.out.println("实现用匕首刺杀!");
        }
    
    }
    public class SwordBehavior implements WeaponBehavior {
    
        @Override
        public void useWeapon() {
            // TODO Auto-generated method stub
            System.out.println("实现用宝剑挥砍!");
        }
    
    }

      其次分析角色,每个角色都会使用武器战斗所以角色都有一个fight(),同时要想实现在游戏中切换武器,必须还得有一个setWeapon(),所以这里建立一个名为Character的抽象类,这个抽象类中有一个fight方法和一个setWeapon方法;

    public abstract class Character {
        WeaponBehavior weaponBehavior;// 注意这里是武器行为,不是具体行为的实现
        public Character() {
        }
        public void fight() {
            weaponBehavior.useWeapon();
        }
    
        public void setWeapon(WeaponBehavior wb) {
            weaponBehavior = wb;
        }
    }

      然后是每一个角色具体实现类,所有角色均继承Character,在每个角色的构造方法中我们都为期初始化了一个武器(在这里是每个武器的具体实现)。

    public class Queen extends Character {
        public Queen(){
         // TODO Auto-generated constructor stub weaponBehavior
    =new KnifeBehavior(); } }
    public class King extends Character {
    
        public King() {
            // TODO Auto-generated constructor stub
            weaponBehavior=new SwordBehavior();
        }
    
    }
    public class Troll extends Character {
    
        public Troll() {
            // TODO Auto-generated constructor stub
            weaponBehavior=new AxeBehavior();
        }
    
    }
    public class Knight extends Character {
    
        public Knight() {
            // TODO Auto-generated constructor stub
            weaponBehavior = new BowAndArrowBehavior();
        }
    
    }

      下面测试一下

    public class Simulator {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Character queen=new Queen();
            queen.fight();
            
            Character king=new King();
            king.fight();
            
            Character troll=new Troll();
            troll.fight();
            
            Character knight=new Knight();
            knight.fight();
        }
    
    }

      打印结果

    实现用匕首刺杀!
    实现用宝剑挥砍!
    实现用斧头劈砍!
    实现用弓箭射击!

      在游戏中切换武器

    public class Simulator {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Character queen=new Queen();
            queen.fight();
            queen.setWeapon(new BowAndArrowBehavior());
            queen.fight();
        }
    
    }

      打印结果

    实现用匕首刺杀!
    实现用弓箭射击!

    以上就是使用策略模式的一个例子,策略模式告诉我们以下原则:

    1.把变化的部分封装起来(例如例子中会变化的武器,或者角色);

    2.多用组合,少用继承(不要只为了复用的目的而使用继承);

    3.针对接口编程,不要针对实现编程。

    思考问题:上面的例子如果新增了一个可以使用短刀的护卫代码该怎样修改(是不是发现原来的代码是不需要修改的)。

     

      

  • 相关阅读:
    [MySql]insert...select 8/10
    秀出Administrator帳戶6/27
    Love
    讀取Gridview的隱藏欄8/22
    水晶報表公式換行8/2
    MySql.Data.MySqlClient.MySqlException 7/9
    mysql的錯誤日誌爆满7/24
    从汇编看c++中的const常量
    可见性和生命期的区别
    比较烦
  • 原文地址:https://www.cnblogs.com/shiwei-bai/p/5038136.html
Copyright © 2020-2023  润新知