设计模式---策略模式

一、什么是策略模式?

策略模式:将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现。

二、光荣与梦想—鸭子应用:策略模式的实现

1、模拟应用背景:

鸭子应用代码如下:

package com.sfd.duck;
/**
 * 抽象类所有种类的鸭子都要继承的类
 * @author sfd
 *
 */
public abstract class Duck {

    /**
     * 鸭子发出声音
     * 通过行为,由超类实现
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }

    /**
     * 用来展示鸭子
     */
    public abstract void display();
}

列举出两个实例:绿脖鸭和红头鸭

package com.sfd.duck;
//绿脖鸭
public class MallardDuck extends Duck{
    public MallardDuck(){
        super();
    }
    @Override
    public void display() {
        System.out.println("我的脖子是绿色的");
    }
}
//红头鸭
public class RedHeadDuck extends Duck{
    public RedHeadDuck(){
        super();
    }
    @Override
    public void display() {
        System.out.println("我的头是红色的");
    }
}

2.让鸭子飞起来

1.方案一:继承
在父类中提供实现方法,子类通过继承获得父类的中的飞行行为;

public void fly(){
    System.out.println("用翅膀飞行");
}

优点:简(cu)单(bao)易用,已有的应用可以快速添加飞行的能力。
缺点:不具有灵活性,对未来的变更支持差(所有Duck类的子类都拥有了用翅膀飞行的能力包括玩具鸭子,显然是不对的)需要通过在子类中覆写飞行的方法以提供新的飞行行为。这很容易造成错误(粗心的程序员忘记覆写)。
这种方案不建议使用

2.方案2:抽象方法
在父类中提供抽象方法,强迫子类实现自己的飞行行为:

public abstract void fly();

优点:足够灵活!再也不会忘记覆写代码了,玩具鸭也不会飞到天上去了;
缺点:代码量太大,每一个子类都要实现飞行方法,尽管实现方法的代码大多数相同;代码重复,没有复用代码。万一再有个bug。。。
这种方案也不建议使用

继承是重用代码的利器,但是继承并不总是最好的工具。

3.最优方案:组合
组合合优先于继承,多用组合,少用继承(Favor composition over inheritance)
什么是组合:在类中增加一个私有域,引用一个已有的类的实例,通过调用引用实例的方法从而获得新的功能,这种设计被称作组合(复合)。

将飞行行为抽象陈接口,在父类中持有该接口,并由该心口代理飞行行为。

优点:足够灵活,复用代码,更易于维护。
缺点:。。。

代码实现:
1.飞行策略接口:

package com.sfd.duck;
public interface FlyingStragety {
    void performFly();
}

2.更改所有鸭子的父类Duck类,增加一个FlyingStragety 成员变量只想具体的飞行策略;

package com.sfd.duck;
/**
 * 抽象类所有种类的鸭子都要继承的类
 * @author sfd
 *
 */
public abstract class Duck {

    private FlyingStragety flyingStragety;


    public void setFlyingStragety(FlyingStragety flyingStragety) {
        this.flyingStragety = flyingStragety;
    }

    /**
     * 鸭子发出声音
     * 通过行为,由超类实现
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }
    /**
     * 用来展示鸭子
     */
    public abstract void display();
    public void fly(){
        flyingStragety.performFly();
    }
}

3.两个鸭子实现类的更改:

package com.sfd.duck;
import com.sfd.duck.impl.FlyWithWin;
public class MallardDuck extends Duck{
    public MallardDuck(){
        super();
        super.setFlyingStragety(new FlyWithWin());
    }
    @Override
    public void display() {
        System.out.println("我的脖子是绿色的");
    }
}
package com.sfd.duck;
import com.sfd.duck.impl.FlyWithWin;
public class RedHeadDuck extends Duck{
    public RedHeadDuck(){
        super();
        super.setFlyingStragety(new FlyWithWin());
    }
    @Override
    public void display() {
        System.out.println("我的头是红色的");
    }
}

这时我们需求有了变动,现在我们需要增加一中不会飞的塑料鸭,这时我们完成起来就十分方便了:

只需要增加一个Duck的实现类和这个新类拥有的新的飞行策略可以了,原先的代码完全不用更改:
新的飞行策略

package com.sfd.duck.impl;
import com.sfd.duck.FlyingStragety;
public class FlyNoWay implements FlyingStragety {
    @Override
    public void performFly() {
        System.out.println("我不会飞行");
    }
}

新类型鸭子—塑料鸭子(不会飞)

package com.sfd.duck;
import com.sfd.duck.impl.FlyNoWay;
public class RubberDuck extends Duck{
    public RubberDuck(){
        super();
        super.setFlyingStragety(new FlyNoWay());
    }
    public void quack() {   
        System.out.println("嘎~嘎~嘎~");
    }
    @Override
    public void display() {
        System.out.println("我是一直橡胶鸭");
    }
}

测试代码:

package com.sfd.duck;
public class Test {
    public static void main(String[] args) {    
        Duck duck=null;
//      duck=new MallardDuck();
//      duck=new RedHeadDuck();
        duck=new RubberDuck();
        duck.display();
        duck.quack();
        duck.fly();
    }
}

这样用策略模式实现的飞行方法就完成了;其实我们的代码还不是很完善的,仔细观察胡发现鸭子叫的方法quack()其实也可以用策略模式来完成,这就叫给大家啦!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值