`

设计模式之策略模式

阅读更多

        先看设计模式的定义:

        策略模式(Strategy Pattern):定义了算法族,分别封装起来,让它们之间可相互替换,次模式让算法的变化独立于使用算法的客户。

         举个例子,大家应该都玩过武侠角色游戏,下面就以角色游戏为背景来介绍。假设公司需要做一款武侠游戏的角色模块,需求是这样:每个角色对应一个名字,每类角色对应一种样子,每个角色拥有一个逃跑、攻击、防御的技能。

          初步的代码:

          

/** 
 * 游戏的角色超类 
 *  
 */  
public abstract class Role  
{  
    protected String name;  
  
    protected abstract void display();  
  
    protected abstract void run();  
  
    protected abstract void attack();  
  
    protected abstract void defend();  
  
}  

 

  
public class RoleA extends Role  {  
    public RoleA(String name)  {  
        this.name = name;  
    }  
  
    @Override  
    protected void display() {  
        System.out.println("样子1");  
    }  
  
    @Override  
    protected void run()  {  
        System.out.println("金蝉脱壳");  
    }  
  
    @Override  
    protected void attack()  {  
        System.out.println("降龙十八掌");  
    }  
  
    @Override  
    protected void defend() {  
        System.out.println("铁头功");  
    }  
  
}  

         没几分钟,你写好了上面的代码,觉得已经充分发挥了OO的思想,正在窃喜,这时候项目经理说,在添加两个角色:

 

         RoleB(样子2,降龙十八掌,铁布衫,金蝉脱壳);

         RoleC(样子1,九阳神功,铁布衫,烟雾弹)。

         于是你觉得没问题,开始写代码,继续继承Role,写成下面的代码:

        

public class RoleB extends Role  {  

    public RoleB(String name)  {  
        this.name = name;  
    }  
  
    @Override  
    protected void display()  {  
        System.out.println("样子2");  
    }  
  
    @Override  
    protected void run()  {  
        System.out.println("金蝉脱壳");//从RoleA中拷贝  
    }  
  
    @Override  
    protected void attack()  
    {  
        System.out.println("降龙十八掌");//从RoleA中拷贝  
    }  
  
    @Override  
    protected void defend()  {  
        System.out.println("铁布衫");  
    }  
  
}

 

public class RoleC extends Role  {  
    public RoleC(String name)  {  
        this.name = name;  
    }  
  
    @Override  
    protected void display()  {  
        System.out.println("样子1");//从RoleA中拷贝  
    }  
  
    @Override  
    protected void run()  {  
        System.out.println("烟雾弹");  
    }  
  
    @Override  
    protected void attack()  {  
        System.out.println("九阳神功");  
    }  
  
    @Override  
    protected void defend() {  
        System.out.println("铁布衫");//从B中拷贝  
    }  
  
}  

        写完之后,你自己似乎没有当初那么自信了,你发现代码中已经存在相当多重复的代码,需要考虑重新设计架构了。于是你想,要不把每个技能都写成接口,有什么技能的角色实现什么接口。简单一想,觉得这想法确实不错。但是实现起来会发现,接口并不能实现代码的复用,每个实现接口的类,还是必须自己写实现。于是,we need change!遵循设计的原则,找出应用中可能需要变化的部分,把它们独立出来,不要和那些不需要的变化的代码混在一起。我们发现,对于每个角色的display、attack、defend和run都有可能变化,于是我们必须把这些独立出来。再根据另一个设计原则:针对接口编程,而不是针对实现编程,于是我们把代码改造成这样:

 

        

public interface IAttack{
        void attack();
}

         

public interface IDefend{
       void defend();
}

         

public interface IDisplay{
        void display();
}

         

public class AttackJY implements IAttack{

        @Override
        public void attack(){
                 System.out.println("九阳神功");
        }

}

         

public class RunJCTQ implements IRun{  
  
    @Override  
    public void run(){  
        System.out.println("金蝉脱壳");  
    }  
  
}  

 

public class DefendTBS implements IDefend {  
  
    @Override  
    public void defend() {  
        System.out.println("铁布衫");  
    }  
  
}  

         这时候需要对Role的代码作出改变:

        

/** 
 * 游戏的角色超类 
 *  
 */  
public abstract class Role {  

    protected String name;  
  
    protected IDefend defend;  
    protected IDisplay display;  
    protected IRun run;  
    protected IAttack attack;  
  
    public Role setDefend(IDefend defend) {  
        this.defend = defend;  
        return this;  
    }  
  
    public Role setDisplay(IDisplay display){  
        this.display = display;  
        return this;  
    }  
  
    public Role setRun(IRun run){  
        this.run = run;  
        return this;  
    }  
  
    public Role setAttack(IAttack attack){  
        this.attack = attack;  
        return this;  
    }  
  
    protected void display(){  
        displayBehavior.display();  
    }  
  
    protected void run(){  
        runBehavior.run();  
    }  
  
    protected void attack(){  
        attackBehavior.attack();  
    }  
  
    protected void defend(){  
        defendBehavior.defend();  
    }  
  
}  

         现在每个角色只需要一个name了:

         

public class RoleA extends Role{  
    public RoleA(String name){  
        this.name = name;  
    }   
}  

         现在我们需要一个金蝉脱壳,降龙十八掌,铁布衫,样子1的角色A只需要这样:

        

public class Test{

        public static void main(String[] args){
                Role roleA = new RoleA("A");
                
                roleA.setAttackBehavior(new AttackXL())//  
                .setDefendBehavior(new DefendTBS())//  
                .setDisplayBehavior(new DisplayA())//  
                .setRunBehavior(new RunJCTQ());  

                System.out.println(roleA.name + ":"); 
 
                roleA.run();  
                roleA.attack();  
                roleA.defend();  
                roleA.display();  

        }
}

         经过这样的修改,现在所有的技能的实现做到了100%的复用,并且随便项目经理需要什么样的角色,对于我们来说只需要动态的设置一下技能和展示方式,这就是策略模式。

          现在我们回到定义,定义上的算法族:其实就是上述例子的技能;定义上的客户:其实就是RoleA、RoleB ......;我们已经定义了一个算法族(各种技能),且根据需求可以进行相互替换,算法(各种技能)的实现独立于客户(角色)。现在是不是很好理解策略模式的定义了。

          附上一张UML图,方便理解:

        

         最后总结一下OO的原则:

         1.封装变化(把可能变化的代码封装起来)

         2.多用组合,少用继承(我们使用组合的方式,为客户设置了算法)

         3.针对接口编程,不针对实现(对于Role类的设计完全的针对角色,和技能的实现没关系)

 

  • 大小: 176.6 KB
分享到:
评论

相关推荐

    设计模式之策略模式 鸭子问题

    设计模式之策略模式 鸭子问题 策略模式是一种经典的设计模式,通过鸭子问题,可以让学习者更好地了解设计模式的概念和实现。策略模式的主要思想是定义一系列的算法,并将每一个算法封装起来,使它们可以相互替换。...

    设计模式之策略模式,商场收银,封装算法

    策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件开发中,我们经常遇到需要根据不同的条件或场景来执行不同算法的情况。策略模式就是为了解决这类问题而提出的,它将每种算法封装到具有共同接口...

    55-Java设计模式之策略模式与状态模式1

    Java 设计模式之策略模式与状态模式 策略模式是 Java 中的一种设计模式,它主要用于解决系统与第三方接口进行数据交互的问题。当系统需要与多种格式的数据进行交互时,使用策略模式可以很好地解决这个问题。例如,...

    设计模式之策略模式源码

    在给定的"设计模式之策略模式源码"工程中,我们可以看到通过一个简单的收银系统来展示策略模式的应用。收银系统是一个常见的业务场景,其中可能涉及多种结算策略,如折扣、满减、会员优惠等。通过策略模式,我们可以...

    设计模式之策略模式(附demo)

    策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在软件工程中,我们经常遇到需要根据不同的条件或时间点执行不同策略的情况。策略模式允许我们将算法族封装到各自独立的类中,使得它们可以互换使用,...

    设计模式之策略模式Android计算器实例

    在这个"设计模式之策略模式Android计算器实例"中,我们将探讨如何在Android应用中使用策略模式来实现一个计算器的功能。 首先,策略模式的核心思想是定义一系列算法,并将每个算法封装起来,使它们可以互相替换。...

    Java设计模式之策略模式

    **策略模式**是Java设计模式中的行为模式之一,它的核心思想是定义一系列的算法,并将每一个算法封装起来,使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户。在Java编程中,策略模式常用于处理那些...

    python 设计模式之策略模式

    python 设计模式之策略模式

    设计模式 之 策略模式 使用c#实现

    在这个"设计模式 之 策略模式 使用c#实现"的案例中,我们将探讨如何在上传收银系统这样的实际场景中应用策略模式。 首先,我们需要理解策略模式的核心概念:策略(Strategy)接口定义了一族算法,实现了策略接口的...

    java设计模式之策略模式

    在"java设计模式之策略模式"的学习中,我们可以通过一个简单的例子来理解它的应用。例如,在一个软件系统中,我们可能需要对不同的数据进行排序,不同的排序算法(如冒泡排序、快速排序、插入排序等)可以被视为策略...

    设计模式之策略模式讲解ppt

    设计模式之策略模式讲解ppt,完整代码详见:https://blog.csdn.net/sinat_35866463/article/details/89094887

    [行为模式] head first 设计模式之策略模式(strategy)

    **策略模式**是一种行为设计模式,它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。 策略模式包含三个主要角色: 1. **策略接口(Strategy...

Global site tag (gtag.js) - Google Analytics