设计模式1-策略模式1

来源:互联网 发布:c语言字符串想加 编辑:程序博客网 时间:2024/06/05 19:26

策略模式的定义

策略模式是一种行为模式,目的就是将我们的行为策略进行分离,提供可供选择的不同的策略。让我们在客户端用使他们可以相互替换、相互调用而不受其他影响。

策略模式的好处

策略模式的好处就是使我们开发人员能够设计出许多可以替换的组件,在不同的场景下面可以使用不同的组件。让客户端拥有不同的变化行为。
下面我们将用一个例子来改造设计模式,这里假定动物这个抽象类

继承实现

/** * 抽象动物超类 * @author qianyi * */public abstract class Animal {    public Animal() {    }    // 动物飞的方法    public void flay() {        System.out.println("---动物飞的方法---");    }    // 动物吃的方法,子类自己覆盖    public void eat() {        System.out.println("--动物吃东西方法--");    }    // 动物游泳方法    public void swi() {        System.out.println("动物游泳方法");    }    public abstract void display();}

动物的实现类之一Cat:

/** * 猫属于动物中的一种 * @author qianyi * 继承了动物的超类,覆盖类eat方法,实现类抽象方法中的displayName方法。 */public class Cat extends Animal {    @Override    public void displayName() {        System.out.println("动物种类:Cat");    }    /**     * 覆盖吃的方法     */    @Override    public void eat() {        System.out.println("猫说:只吃鱼");    }}

调用Cat方法:

public class Test {    public static void main(String[] args) {        Animal animal = new Cat();        animal.displayName();        animal.eat();        animal.swi();    }}

结果:

动物种类:Cat猫说:只吃鱼动物游泳方法

从上面的结果来看,我们可以看到动物子类猫具有swi方法,肯定是不合理的,猫肯定是不会游泳的,不会飞。这样就可以看出设计有问题了,举一反三,加入现在鱼也继承了Animal类,那么鱼肯定是不会飞的,我们可以发现不同动物有不同的行为。如果以后要增加一种行为,我们在Ainmal中增加一种行为,那么子类都需要增加这种行为肯定是不合理的。我们希望不同的动物拥有不同的行为,而且行为之间是有差异的,比如eat方法,猫这种动物需要吃鱼,鱼这种动物吃的食物小虾。这就需要用的策略模式。

策略解决继承带来的痛点,继承之后,子类都具有,如果采用覆盖则代码冗余。不同子类有不同的行为:实现行为的组合,猫只有吃和爬行的行为,鱼有游泳的行为,从而将我们的行为抽象出来,具体的角色持有自己想要的行为




策略实现的步骤:

1.分析我们项目中变化部分和不变化部分,提取变化部分

上面例子就可以看出动物的不同行为输入变化,变化的部分:吃的行为、飞的行为、游泳的行为,都是变化的。这个时候需要将我们的行为抽象为接口+实现

飞的行为

/** * 飞的行为,横着飞、躺着飞,具体的行为很多中,具体去实现这个飞的行为 * @author qianyi */public interface FlyBehavior {    void fly();}

吃的行为

/** * 吃的行为,策略的抽象 * @author qianyi */public interface EatBehavior {    void eat();}

游泳行为

/** * 游泳的行为,策略的抽象 * @author qianyi */public interface SwimBehavior {    void swim();}

2.实现具体的策略和算法和行为

抽象策略FlyBehavior具体的行为策略

/** * 具体的策略1 * 具体的飞行方式1:BadFlay * @author qianyi */public class BadFly implements FlyBehavior {    @Override    public void fly() {        // TODO Auto-generated method stub        System.out.println("飞行的方式1---BadFly");    }}
/** *具体的策略2 *飞行的方式二 * @author qianyi */public class GoodFly implements FlyBehavior {    @Override    public void fly() {        // TODO Auto-generated method stub        System.out.println("飞行的方式1...GoodFly");    }}

策略EatBehavior具体的行为策略:

/** *  吃的具体行为策略:吃鱼 * @author qianyi */public class EatFish  implements EatBehavior{    @Override    public void fly() {        System.out.println("吃的食物鱼:Food");    }}
/** * 吃的具体行为策略:吃水 * @author qianyi */public class EatWater implements EatBehavior {    @Override    public void fly() {        System.out.println("吃的食物:Water");    }}

3.具体的角色,自由组合我们的行为。

/** * 动物猫-具体的应用场景,持有两个抽象策略EatBehavior和FlyBehavior策略 * @author qianyi */public  class Cat {    private EatBehavior eatBehavior;    private FlyBehavior flyBehavior;    public EatBehavior getEatBehavior() {        return eatBehavior;    }    public void setEatBehavior(EatBehavior eatBehavior) {        this.eatBehavior = eatBehavior;    }    public FlyBehavior getFlyBehavior() {        return flyBehavior;    }    public void setFlyBehavior(FlyBehavior flyBehavior) {        this.flyBehavior = flyBehavior;    }    public void eat(){        eatBehavior.eat();    }    public void fly(){        flyBehavior.fly();    }}

4.具体应用场景测试:

    public static void main(String[] args) {        Cat cat1=new Cat();        EatFish eat1=new EatFish();        cat1.setEatBehavior(eat1);        System.out.println("cat1喜欢吃:");        eat1.eat();        Cat cat2=new Cat();        EatWater eat2=new EatWater();        BadFly badfly=new BadFly();        System.out.println("cat2喜欢吃:");        cat2.setEatBehavior(eat2);        cat2.setFlyBehavior(badfly);        cat2.eat();        cat2.fly();        /**        cat1喜欢吃:        吃的食物:Food        cat2喜欢吃:        吃的食物:Water        飞行的方式1---BadFly         */         //从上面可以看到cat2还有飞的行为,如果新增加一了一种食物肉,实现EatBehavior就可以了。具体应用场景直接初始化自己的行为状态,也不会影响到其他对象。    }
cat1喜欢吃:吃的食物:Foodcat2喜欢吃:吃的食物:Water飞行的方式1---BadFly

通过上面可以看出策略模式有以下角色构成:
1、抽象策略(Strategy)角色:抽象策略角色由抽象类或接口来承担,它给出具体策略角色需要实现的接口;(吃的行为、飞的行为、)
2、具体策略(ConcreteStrategy)角色:实现封装了具体的算法或行为;(具体吃的行为EatFish\EatWater、具体飞的行BadFly\GoodFly为)
3、场景(Context)角色:持有抽象策略类的引用。
应用场景动物猫持有EatBehavior和FlyBehavior两个策略.
通过以上的代码可以看到,我们在项目中将我们变化的抽离出来成策略,在使用的时候直接注入对应的行为。

注意点:

*1.分析项目中变化部分与不变化部分,继承很好的实现了代码的复用,但是有的子类都需要实现这个行为。
*2.多用组合少用继承;用行为组合,而不是行为的继承,更有弹性
不同的动物拥有不同的行为,而且行为之间是有差异的,比如eat方法,有的猫喜欢吃鱼,有的猫喜欢吃肉,那么我们只需要写一个EatBehavior的行为实现,从而消除了继承带来的代码冗余。

原创粉丝点击