设计模式学习笔记-策略模式
设计模式学习笔记-策略模式
贲大侠 发表于1年前
设计模式学习笔记-策略模式
  • 发表于 1年前
  • 阅读 6
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 读《Head First》一些简单的个人总结。

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

        上面这段话是《Head First》对第一章策略模式的最后总结,起初看书时候我十分看不明白书中所说的算法族是啥意思,看书中的代码“封装行为”,一个接口,多个类实现,每个实现类都被比喻做算法族。

比如:
       一只鸭子(可能是玩具鸭子,还可能是有生命的鸭子)。它可以飞,可以叫。把它“飞”和“叫”看做行为。行为分为很多种,比如玩具鸭子不具备叫的功能,有生命的鸭子可以叫,玩具鸭子不能飞,有生命的鸭子可以飞。有的鸭子也可能叫声不同,非得方式也不同。这个时候封装一个“飞”的行为,然后用多个类实现。具体看下面的代码:

//飞行行为接口
public interface FlyBehavior {
    //飞
    public void fly();
}
//实现飞行接口,这个实现类被定义为不能飞
public class FlyNoWay implements FlyBehavior{
    //实现飞行行为方法
    @Override
	public void fly() {
		System.out.println("不能飞");
	}
}
//实现飞行接口,这个实现类被定义为可以飞
public class FlyWithWings implements FlyBehavior{
    //实现飞行方法
	@Override
	public void fly() {
		System.out.println("可以飞哦");
	}
}

        每一个实现类(行为)被看做一个算法族。同理,鸭子叫的行为也和上面实现方式一样,具体看下面的代码:

//鸭子叫行为接口
public interface QuackBehavior {
    //叫
	public void quack();
}
//实现叫行为接口,这个接口被定义为哇哇叫
public class Squeak implements QuackBehavior {
    //鸭子哇哇叫
	@Override
	public void quack() {
		System.out.println("哇哇哇");
	}
}
//实现叫行为,这个接口被定义为嘎嘎叫
public class Quack implements QuackBehavior{
    //鸭子嘎嘎叫
	@Override
	public void quack() {
		System.out.println("嘎嘎嘎");
	}
}
//实现叫行为,这个接口被定义为不能叫
public class MuteQuack implements QuackBehavior{
    //不能叫
	@Override
	public void quack() {
		System.out.println("无法叫");
	}
}

        这个时候,我们要实现很多个鸭子都有不同的“飞”和“叫”的行为。        

        定义一只鸭子抽象类当做父类,因为鸭子有很多种,看上去不同,但本质是一样的,都是鸭子。(我的思维比较逆向...觉得我顺序不对的大牛请忍耐一下..)

public abstract class Duck {
    //书中说道,鸭子里面要"有一个",也就是,每个鸭子都"有一个"飞行行为和叫行为,
    //代码上来看就是在鸭子类里面声明"飞行为"和"叫的行为",也就是下面这俩
    //这样每只集成了父类鸭子的子鸭子都会引用实现行为接口的对象
	FlyBehavior flybehavior;

	QuackBehavior quackBehavior;

    //写一个方法取代 fly()
	public void performQuack() {
		quackBehavior.quack();//父类鸭子对象不亲自处理使用 嘎嘎嘎 还是 哇哇哇 而是委托给行为引用的对象
	}

    public void performFly() {
		flybehavior.fly();
	}
}

        然后开始写子鸭子

//子鸭子继承父鸭子
public class MallardDuck extends Duck{
	public MallardDuck(){
		quackBehavior = new Squeak();//这只鸭子可以哇哇叫
		flybehavior= new FlyWithWings();//这只鸭子可以飞
		this.display();
	}
	
	public void display(){
		System.out.println("红鸭子!");
	}
}
//子鸭子继承父鸭子
public class ModelDuck extends Duck{
	public ModelDuck(){
		flybehavior= new FlyNoWway();//这鸭子不能飞
		quackBehavior = new Quack();//可以叫
		this.dispay();
	}
	
	public void dispay(){
		System.out.println("玩具鸭");
	}
}

        然后编写个测试类感受一下

public class MinDuckSimulator {
 public static void main(String[] args) {
		Duck mallardDuck = new MallardDuck();
        //这里会调用红鸭子继承来的performQuack()方法,进而委托给行为对象来处理。
		mallardDuck.performFly();
		mallardDuck.performQuack();

        Duck modelDuck = new ModelDuck();
		modelDuck.performFly();
		modelDuck.performQuack();
 }
}

        运行结果:

红鸭子
可以飞
哇哇哇

模型鸭
不能飞
嘎嘎嘎

        接下来实现鸭子动态设定行为

public abstract class Duck {
    //书中说道,鸭子里面要"有一个",也就是,每个鸭子都"有一个"飞行行为和叫行为,
    //代码上来看就是在鸭子类里面声明"飞行为"和"叫的行为",也就是下面这俩
    //这样每只集成了父类鸭子的子鸭子都会引用实现行为接口的对象
	FlyBehavior flybehavior;

	QuackBehavior quackBehavior;

    //写一个方法取代 fly()
	public void performQuack() {
		quackBehavior.quack();//父类鸭子对象不亲自处理使用 嘎嘎嘎 还是 哇哇哇 而是委托给行为引用的对象
	}

    public void performFly() {
		flybehavior.fly();
	}

    //我们在父类鸭子类里面增加两个set方法
    public void setFlyBehavior(FlyBehavior fb) {
		flybehavior= fb;
	}

	public void setQuackBehavior(QuackBehavior qb) {
		quackBehavior = qb;
	}
}

        测试

public class MinDuckSimulator {
 public static void main(String[] args) {
		Duck mallardDuck = new MallardDuck();
		mallardDuck.performFly();
        //之前红鸭子默认是用哇哇哇的方式来叫
        mallardDuck.setQuackBehavior(new Quack());//在这里调用继承来的set方法 动态设置鸭子的叫声
		mallardDuck.performQuack();

        Duck modelDuck = new ModelDuck();
		modelDuck.performFly();
		modelDuck.performQuack();
 }
}

结果

红鸭子
可以飞
嘎嘎嘎

模型鸭
不能飞
嘎嘎嘎

        利用继承来提供鸭子行为也有很多缺点,比如有的代码在多个子类中有很多重复,并且很难知道鸭子所有的行为。但策略模式提供了管理相关的算法族的办法,恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码

标签: 设计模式
共有 人打赏支持
粉丝 0
博文 11
码字总数 12261
×
贲大侠
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: