设计模式——策略模式

设计模式——策略模式

本片博文学习尚硅谷韩老师《设计模式》课程所做,在此非常感谢!

概述

策略模式的基本介绍

  • 策略模式(Strategy Pattern)中,定义算法族(策略组),分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户;
  • 这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组合/聚合,少用继承(客户通过组合方式使用策略);

注意事项

  • 策略模式的关键是:分析项目中变化部分与不变部分;
  • 策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性;
  • 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if…else if…else);
  • 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展;
  • 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大;

UML
在这里插入图片描述

问题引入

编写鸭子项目,具体要求如下:

  • 有各种鸭子(比如 野鸭、北京鸭、水鸭等, 鸭子有各种行为,比如 叫、飞行等)
  • 能够显示鸭子的信息
  • 能够如上面所描述的一样,只通过一行代码(策略或者行为)就可以修改某个鸭子的属性;

我们通过策略模式来实现这个需求

编码实现

UML

首先构建出这个需求的UML图,如下所示:
在这里插入图片描述

编码

我们创建行为接口,分别是飞的行为游泳的行为叫的行为,如下所示:

package edu.hebeu.strategy.strategys.flybehavior;

public interface FlyBehavior {
	
	/**
	 * 飞的方法
	 */
	void fly();
}

package edu.hebeu.strategy.strategys.swimbehavior;

public interface SwimBehavior {

	/**
	 * 游泳的方法
	 */
	void swim();
}

package edu.hebeu.strategy.strategys.quackbehavior;

public interface QuackBehavior {
	
	/**
	 * 叫的方法
	 */
	void quack();
}

然后在这个三个行为接口的基础上各自实现几个对应的子类,如飞的行为接口的实现类:擅长飞不擅长飞不会飞游泳的行为接口的实现类有:擅长游泳不擅长游泳不会游泳叫的行为接口的实现类:GaGaQuackBehaviorGeGeQuackBehaviorNotQuackBehavior,具体编码如下:

飞的行为接口的实现类

package edu.hebeu.strategy.strategys.flybehavior;

public class GoodFlyBehavior implements FlyBehavior{

	@Override
	public void fly() {
		System.out.println("非常擅长飞");
	}

}

package edu.hebeu.strategy.strategys.flybehavior;

public class BadFlyBehavior implements FlyBehavior {

	@Override
	public void fly() {
		System.out.println("飞的技术很一般");
	}

}

package edu.hebeu.strategy.strategys.flybehavior;

public class NotFlyBehavior implements FlyBehavior{

	@Override
	public void fly() {
		System.out.println("不会飞");
	}

}

游泳的行为接口的实现类

package edu.hebeu.strategy.strategys.swimbehavior;

public class GoodSwimBehavior implements SwimBehavior{

	@Override
	public void swim() {
		System.out.println("非常擅长游泳");
	}

}
package edu.hebeu.strategy.strategys.swimbehavior;

public class BadSwimBehavior implements SwimBehavior{

	@Override
	public void swim() {
		System.out.println("游泳技术一般");
	}

}

package edu.hebeu.strategy.strategys.swimbehavior;

public class NotSwimBehavior implements SwimBehavior{

	@Override
	public void swim() {
		System.out.println("不会游泳");
	}

}

叫的行为接口的实现类

package edu.hebeu.strategy.strategys.quackbehavior;

public class GaGaQuackBehavior implements QuackBehavior{

	@Override
	public void quack() {
		System.out.println("嘎嘎嘎~~~");
	}
	
}

package edu.hebeu.strategy.strategys.quackbehavior;

public class GeGeQuackBehavior implements QuackBehavior {

	@Override
	public void quack() {
		System.out.println("咯咯咯~~~");
	}

}

package edu.hebeu.strategy.strategys.quackbehavior;

public class NotQuackBehavior implements QuackBehavior {

	@Override
	public void quack() {
		System.out.println("不能叫");
	}

}

此时所有的行为(策略)就准备完毕了,我们此时创建一个抽象的使用类Duck,然后让这个类将所有的行为接口聚合,如下:

package edu.hebeu.strategy.user;

import edu.hebeu.strategy.strategys.flybehavior.FlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.QuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.SwimBehavior;

/**
 * 所有的鸭子的抽象基类
 * @author 13651
 *
 */
public abstract class Duck {
	
	// 聚合所有的策略
	protected FlyBehavior fly;
	protected QuackBehavior quack;
	protected SwimBehavior swim;
	
	/**
	 * 展示鸭子的所有信息
	 */
	public abstract void display();
	
	/**
	 * 飞的方法
	 */
	public final void fly() {
		if(fly != null) { // 如果fly不为null,就调用fly的fly()方法
			fly.fly();
			return;
		}
		System.out.println("鸭子会飞"); // 程序执行到此,说明fly为null
	}
	
	/**
	 * 叫的方法
	 */
	public final void quack() {
		if(quack != null) { // 如果quack不为null,就调用quack的quack()方法
			quack.quack();
			return;
		}
		System.out.println("鸭子会叫"); // 程序执行到此,说明quack为null
	}
	
	/**
	 * 游泳的方法
	 */
	public final void swim() {
		if(swim != null) { // 如果swim不为null,就调用swim的swim()方法
			swim.swim();
			return;
		}
		System.out.println("鸭子会游泳"); // 程序执行到此,说明swim为null
	}
	
	public void setFly(FlyBehavior fly) {
		this.fly = fly;
	}
	
	public void setQuack(QuackBehavior quack) {
		this.quack = quack;
	}
	
	public void setSwim(SwimBehavior swim) {
		this.swim = swim;
	}
	
}

然后创建具体的使用类(BeiJingDuckTangLaoDuckWildDuckToyDuck),这些类都继承上述的抽象类,如下:

package edu.hebeu.strategy.user;

import edu.hebeu.strategy.strategys.flybehavior.NotFlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GaGaQuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.GoodSwimBehavior;

public class BeiJingDuck extends Duck{

	public BeiJingDuck() {
		fly = new NotFlyBehavior();
		quack = new GaGaQuackBehavior();
		swim = new GoodSwimBehavior();
	}

	@Override
	public void display() {
		System.out.println("------------------这是北京鸭-----------------");
		fly();
		quack();
		swim();
		System.out.println("---------------------------------------------");
	}
	
}

package edu.hebeu.strategy.user;

import edu.hebeu.strategy.strategys.flybehavior.NotFlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GaGaQuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.NotSwimBehavior;

public class TangLaoDuck extends Duck{

	public TangLaoDuck() {
		fly = new NotFlyBehavior();
		quack = new GaGaQuackBehavior();
		swim = new NotSwimBehavior();
	}
	
	@Override
	public void display() {
		System.out.println("------------------这是唐老鸭-----------------");
		fly();
		quack();
		swim();
		System.out.println("---------------------------------------------");
	}

}

package edu.hebeu.strategy.user;

import edu.hebeu.strategy.strategys.flybehavior.GoodFlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GeGeQuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.GoodSwimBehavior;

public class WildDuck extends Duck{

	public WildDuck() {
		fly = new GoodFlyBehavior();
		quack = new GeGeQuackBehavior();
		swim = new GoodSwimBehavior();
	}
	
	@Override
	public void display() {
		System.out.println("------------------这是野鸭-----------------");
		fly();
		quack();
		swim();
		System.out.println("---------------------------------------------");
	}

}

package edu.hebeu.strategy.user;

import edu.hebeu.strategy.strategys.flybehavior.NotFlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GeGeQuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.BadSwimBehavior;

public class ToyDuck extends Duck{

	public ToyDuck() {
		fly = new NotFlyBehavior();
		quack = new GeGeQuackBehavior();
		swim = new BadSwimBehavior();
	}
	
	@Override
	public void display() {
		System.out.println("------------------这是玩具鸭-----------------");
		fly();
		quack();
		swim();
		System.out.println("---------------------------------------------");
	}
}

此时策略模式就搭建完毕了,我们通过下面的测试类来使用一下上面的代码,并实现上述的需求,如下所示:

package edu.hebeu.strategy;

import java.util.Scanner;

import edu.hebeu.strategy.strategys.flybehavior.BadFlyBehavior;
import edu.hebeu.strategy.strategys.flybehavior.GoodFlyBehavior;
import edu.hebeu.strategy.strategys.flybehavior.NotFlyBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GaGaQuackBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.GeGeQuackBehavior;
import edu.hebeu.strategy.strategys.quackbehavior.NotQuackBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.BadSwimBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.GoodSwimBehavior;
import edu.hebeu.strategy.strategys.swimbehavior.NotSwimBehavior;
import edu.hebeu.strategy.user.BeiJingDuck;
import edu.hebeu.strategy.user.TangLaoDuck;
import edu.hebeu.strategy.user.ToyDuck;
import edu.hebeu.strategy.user.WildDuck;

public class Client {
	
	private static Scanner SCANNER = new Scanner(System.in);
	private static String KEYWORD = null;
	
	private static BeiJingDuck BEIJING_DUCK = new BeiJingDuck();
	private static TangLaoDuck TANGLAO_DUCK = new TangLaoDuck();
	private static WildDuck WILD_DUCK = new WildDuck();
	private static ToyDuck TOY_DUCK = new ToyDuck();
	
	public static void main(String[] args) {
		
		while(true) {
			System.out.println("1. 查看指定鸭子信息");
			System.out.println("2. 修改鸭子信息");
			System.out.println("3. 查看全部鸭子");
			
			KEYWORD = SCANNER.next();
			if (KEYWORD.equals("1")) {
				selectDuckInfo();
			} else if (KEYWORD.equals("2")) {
				alterDuckInfo();
			} else if (KEYWORD.equals("3")) {
				BEIJING_DUCK.display();
				TANGLAO_DUCK.display();
				WILD_DUCK.display();
				TOY_DUCK.display();
			} else {
				System.out.println("bye~~~~");
				break;
			}
		}
		
	}
	
	/**
	 * 查询指定鸭子信息的方法
	 */
	public static void selectDuckInfo() {
		while (true) {
			System.out.println("b(北京鸭)");
			System.out.println("t(唐老鸭)");
			System.out.println("w(野鸭)");
			System.out.println("toy(玩具鸭)");
			
			KEYWORD = SCANNER.next();
			if (KEYWORD.equals("b")) {
				BEIJING_DUCK.display();
			} else if (KEYWORD.equals("t")) {
				TANGLAO_DUCK.display();
			} else if (KEYWORD.equals("w")) {
				WILD_DUCK.display();
			} else if (KEYWORD.equals("toy")) {
				TOY_DUCK.display();
			} else {
				System.out.println("quit--");
				break;
			}
			
		}
	}
	
	
	/**
	 * 修改指定鸭子信息的方法
	 */
	public static void alterDuckInfo() {
		while (true) {
			System.out.println("b(北京鸭)");
			System.out.println("t(唐老鸭)");
			System.out.println("w(野鸭)");
			System.out.println("toy(玩具鸭)");
			System.out.println("其他退出");
			System.out.println("选项直接选择序号即可");
			
			KEYWORD = SCANNER.next();
			if (KEYWORD.equals("b")) {
				System.out.print("北京鸭的飞行能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					BEIJING_DUCK.setFly(new GoodFlyBehavior());
				} else if ("2".equals(KEYWORD)) {
					BEIJING_DUCK.setFly(new BadFlyBehavior());
				} else if ("3".equals(KEYWORD)) {
					BEIJING_DUCK.setFly(new NotFlyBehavior());
				}
				
				System.out.print("北京鸭的游泳能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					BEIJING_DUCK.setSwim(new GoodSwimBehavior());
				} else if ("2".equals(KEYWORD)) {
					BEIJING_DUCK.setSwim(new BadSwimBehavior());
				} else if ("3".equals(KEYWORD)) {
					BEIJING_DUCK.setSwim(new NotSwimBehavior());
				}
				
				System.out.print("北京鸭的怎么叫:1. 嘎嘎嘎~~~、2. 咯咯咯~~~、3. 不能叫");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					BEIJING_DUCK.setQuack(new GaGaQuackBehavior());
				} else if ("2".equals(KEYWORD)) {
					BEIJING_DUCK.setQuack(new GeGeQuackBehavior());
				} else if ("3".equals(KEYWORD)) {
					BEIJING_DUCK.setQuack(new NotQuackBehavior());
				}
				
			} else if (KEYWORD.equals("t")) {
				System.out.print("唐老鸭的飞行能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TANGLAO_DUCK.setFly(new GoodFlyBehavior());
				} else if ("2".equals(KEYWORD)) {
					TANGLAO_DUCK.setFly(new BadFlyBehavior());
				} else if ("3".equals(KEYWORD)) {
					TANGLAO_DUCK.setFly(new NotFlyBehavior());
				}
				
				System.out.print("唐老鸭的游泳能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TANGLAO_DUCK.setSwim(new GoodSwimBehavior());
				} else if ("2".equals(KEYWORD)) {
					TANGLAO_DUCK.setSwim(new BadSwimBehavior());
				} else if ("3".equals(KEYWORD)) {
					TANGLAO_DUCK.setSwim(new NotSwimBehavior());
				}
				
				System.out.print("唐老鸭的怎么叫:1. 嘎嘎嘎~~~、2. 咯咯咯~~~、3. 不能叫");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new GaGaQuackBehavior());
				} else if ("2".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new GeGeQuackBehavior());
				} else if ("3".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new NotQuackBehavior());
				}
				
			} else if (KEYWORD.equals("w")) {
				System.out.print("野鸭的飞行能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					WILD_DUCK.setFly(new GoodFlyBehavior());
				} else if ("2".equals(KEYWORD)) {
					WILD_DUCK.setFly(new BadFlyBehavior());
				} else if ("3".equals(KEYWORD)) {
					WILD_DUCK.setFly(new NotFlyBehavior());
				}
				
				System.out.print("野鸭的游泳能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					WILD_DUCK.setSwim(new GoodSwimBehavior());
				} else if ("2".equals(KEYWORD)) {
					WILD_DUCK.setSwim(new BadSwimBehavior());
				} else if ("3".equals(KEYWORD)) {
					WILD_DUCK.setSwim(new NotSwimBehavior());
				}
				
				System.out.print("野鸭的怎么叫:1. 嘎嘎嘎~~~、2. 咯咯咯~~~、3. 不能叫");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new GaGaQuackBehavior());
				} else if ("2".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new GeGeQuackBehavior());
				} else if ("3".equals(KEYWORD)) {
					TANGLAO_DUCK.setQuack(new NotQuackBehavior());
				}
				
			} else if (KEYWORD.equals("toy")) {
				System.out.print("玩具鸭的飞行能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TOY_DUCK.setFly(new GoodFlyBehavior());
				} else if ("2".equals(KEYWORD)) {
					TOY_DUCK.setFly(new BadFlyBehavior());
				} else if ("3".equals(KEYWORD)) {
					TOY_DUCK.setFly(new NotFlyBehavior());
				}
				
				System.out.print("玩具鸭的游泳能力:1. 非常好、2. 不好、3. 不会");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TOY_DUCK.setSwim(new GoodSwimBehavior());
				} else if ("2".equals(KEYWORD)) {
					TOY_DUCK.setSwim(new BadSwimBehavior());
				} else if ("3".equals(KEYWORD)) {
					TOY_DUCK.setSwim(new NotSwimBehavior());
				}
				
				System.out.print("玩具鸭的怎么叫:1. 嘎嘎嘎~~~、2. 咯咯咯~~~、3. 不能叫");
				KEYWORD = SCANNER.next();
				if ("1".equals(KEYWORD)) {
					TOY_DUCK.setQuack(new GaGaQuackBehavior());
				} else if ("2".equals(KEYWORD)) {
					TOY_DUCK.setQuack(new GeGeQuackBehavior());
				} else if ("3".equals(KEYWORD)) {
					TOY_DUCK.setQuack(new NotQuackBehavior());
				}
				
			}
			System.out.println("quit--");
			break;
			
		}
	}
}

测试

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值