为什么我们使用策略模式?

时间:2015-12-13 06:52:12

标签: java design-patterns strategy-pattern

我刚刚从互联网上了解了战略模式的真正含义。但我想知道它如何改进我的代码。例如,我在互联网上找到以下代码。这是名为Animal的超类:

abstract public class Animal {
    private String name;
    private int weight;
    private String sound;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setWeight(int weight){
        if(weight > 0){
            this.weight = weight;
        }else {
            System.out.println("Weight must be bigger than 0");
        }
    }

    public int getWeight(){
        return weight;
    }

    public void setSound(String sound){
        this.sound = sound;
    }
    public String getSound(){
        return sound;
    }

    public void specialMethod(){
        System.out.println("Ok");
    }
}

这是名为Dog的子类:

public class Dog extends Animal {
    public void digHole(){
        System.out.println("Dig a hole");
    }

    public Dog(){
        super();
        setSound("bark");
    }

    public void testSuper(Animal obj){
        System.out.println(obj.getName());
    }
}

在教程中,它说如果我们想增加飞行能力,以便我可以检查狗是否可以飞行。像这样直接添加代码很糟糕,如下面的代码所示。

具有附加飞行能力方法的超类动物

abstract public class Animal {
    private String name;
    private int weight;
    private String sound;

    // Add fly method to the superclass which is a bad idea 
    public String fly(){
        return " I am flying ";
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setWeight(int weight){
        if(weight > 0){
            this.weight = weight;
        }else {
            System.out.println("Weight must be bigger than 0");
        }
    }

    public int getWeight(){
        return weight;
    }

    public void setSound(String sound){
        this.sound = sound;
    }

    public String getSound(){
        return sound;
    }

    public void specialMethod(){
        System.out.println("Ok");
    }
}

使用策略模式,我们可以使用方法fly创建名为Flys的接口,允许任何子类实现该方法,因此如教程所示,我创建了名为Flys的接口,其中包含2个实现接口的子类:

public interface Flys {
    String fly();
}

class ItFlys implements Flys{
    public String fly(){
        return "Flying high";
    }
}

class CantFly implements Flys{
    public String fly(){
        return "I can't fly";
    }
}

一旦我创建了界面,我就可以重构Animal类,

abstract public class Animal {
    private String name;
    private int weight;
    private String sound;
    Flys flyingType; // Add an object of the interface to the superclass 

    public String tryToFly(){ // add a new method tryToFly
        return flyingType.fly();
    }

    // Adding another method named setFlyingAbility 
    public void setFlyingAbility(Flys newFlyType){
        flyingType = newFlyType;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setWeight(int weight){
        if(weight > 0){
            this.weight = weight;
        }else {
            System.out.println("Weight must be bigger than 0");
        }
    }

    public int getWeight(){
        return weight;
    }

    public void setSound(String sound){
        this.sound = sound;
    }

    public String getSound(){
        return sound;
    }

    public void specialMethod(){
        System.out.println("Ok");
    }
}

现在,在我的Dog子类中,我只需添加另一个代码

public class Dog extends Animal {
    public Dog(){
        super();
        setSound("bark");
        flyingType = new CantFly(); // I set flyingType object 
    }

    public void digHole(){
        System.out.println("Dig a hole");
    }

    public void testSuper(Animal obj){
        System.out.println(obj.getName());
    }
}

最后一堂课是我可以执行所有代码的地方,检查我的Dog课程是否可以飞行。

public class AnimalPlay {
    public static void main(String args[]){
        Animal sparky = new Dog();
        Animal tweety = new Bird();
        System.out.println("Dog " + sparky.tryToFly()); // the result is I can't fly 
        System.out.println("Bird " + tweety.tryToFly()); // the result is I am flying 
        sparky.setFlyingAbility(new ItFlys());
        System.out.println("Dog " + sparky.tryToFly()); // the result is I am flying 
    }
}

我的问题是,如果我仍然以传统方式添加fly()方法,它会给出相同的结果,不是吗?

将fly()方法添加到超类中,以便我可以覆盖我的Dog类中的fly()方法,但这不是一个好主意。

abstract public class Animal {
    private String name;
    private int weight;
    private String sound;

    // Add fly method to the superclass which is a bad idea 
    public String fly(){
        return " I am flying ";
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setWeight(int weight){
        if(weight > 0){
            this.weight = weight;
        }else {
            System.out.println("Weight must be bigger than 0");
        }
    }

    public int getWeight(){
        return weight;
    }

    public void setSound(String sound){
        this.sound = sound;
    }
    public String getSound(){
        return sound;
    }

    public void specialMethod(){
        System.out.println("Ok");
    }
}

2 个答案:

答案 0 :(得分:2)

  

我的问题是,如果我仍然以传统的方式添加fly()方法,它会得到相同的结果,不是吗?

答案是“不”。

  1. 策略模式允许您将行为移动到单独的类中,这是通过SOLID原则很好的' S' - 单一责任。您需要学习机器人或人类以及“吠叫”的图像。 - 你不需要让它们继承动物基类。而且你也不需要在每节课中实施吠叫。
  2. 在基类中拥有所有属性也不好,因为它反对SOLID' L' - Liskou替换。如果猴子不需要在基础动物类中实施吠叫怎么办?
  3. 策略模式允许您根据SOLID' I'设计相应的代码。 - 接口隔离 - 只需使IAnimalAction接口进行许多实现吠叫并将IAnimalAction属性分配给所需的动物类(作为属性或作为另一个实现的接口)
  4. 策略也有助于SOLID' D' - 你可以注射所需的动物策略(吠叫,飞行)而不让每只动物都知道它
  5. 我们可以继续寻找其他奖金。但你可以看到一张图片

    祝你好运!

答案 1 :(得分:0)

我不确定哪个是第一个,但战略模式与任何其他行为模式一样是open close principle的特定实例。通常,您希望更改对象的行为,而无需更改其代码。这在可扩展性,可维护性和一致性方面具有深远的影响。