策略模式(strategy)

一.策略模式是什么

策略模式是一种行为型对象模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换。这样,算法可以独立于使用它的客户端而变化‌‌。

策略者模式的核心思想是将一系列的算法封装到一系列的策略类里,作为一个抽象策略类的子类。具体策略角色包装了相关的算法或行为,而环境角色持有一个策略类的引用,这样可以在不影响到客户端的情况下更换算法‌。

策略者模式的优点在于它使得算法可以在不影响到客户端的情况下发生变化。通过将算法封装到独立的类中,并使它们具有共同的接口,策略者模式允许在运行时选择不同的算法实现,从而提高了程序的灵活性和可扩展性‌

二.类图

三.实例

示例一:

商场打折,一共有两种策略,满300打8折,满400打7折。UML图如下

Buy.java

java 复制代码
package 策略模式;

public class Buy {
	private Discount discount=new Discount();
	private double cost;
	Buy(double cost){
	this.cost=cost;	
	}
	double getcost() {
		return cost;
	}
	Discount getdiscount() {
		return discount;
	}
}

Discount.java

java 复制代码
package 策略模式;

public class Discount {
protected double discountpercent;
protected double discountprice;
void dodiscount(double originalprice) {
	if(originalprice>400.00) {
		new stratage1(originalprice);
	}
	else if(originalprice>300.00) {
		new stratege2(originalprice);
	}
	else {
		new stratege3(originalprice);
	}
	
}
void setdisp(double discountpercent) {
	this.discountpercent=discountpercent;
}
void print(){};
}

Stratege1.java

java 复制代码
package 策略模式;

public class stratage1 extends Discount{
	stratage1(double originalprice){
		print();
		setdisp(0.7);
		discountprice=originalprice*discountpercent;
		System.out.printf("原来的价格是:");
		System.out.println(originalprice);
		System.out.printf("打完折后的价格是:");
		System.out.println(discountprice);
	}

	void print() {
		// TODO Auto-generated method stub
		System.out.println("因为购物的价格在400元以上,打7折");
	}
	
	
}

Stratege2.java

java 复制代码
package 策略模式;

public class stratege2 extends Discount{
	stratege2(double originalprice){
		print();
		setdisp(0.8);
		discountprice=originalprice*discountpercent;
		System.out.printf("原来的价格是:");
		System.out.println(originalprice);
		System.out.printf("打完折后的价格是:");
		System.out.println(discountprice);
	}

	@Override
	void print() {
		// TODO Auto-generated method stub
		System.out.printf("因为商品价格介于300到400之间,打8折");
	}
}

Stratege3.java

java 复制代码
package 策略模式;

public class stratege3 extends Discount{
	stratege3(double originalprice){
		print();
		setdisp(1);
		discountprice=originalprice*discountpercent;
		System.out.printf("原来的价格是:");
		System.out.println(originalprice);
		System.out.printf("打完折后的价格是:");
		System.out.println(discountprice);
	}

	@Override
	void print() {
		// TODO Auto-generated method stub
		System.out.printf("因为商品的价格小于300元,所以不打折\n");

	}
}

A.java(主函数)

java 复制代码
package 策略模式;

public class A {
	public static void main(String[] args) {
		Buy buy1=new Buy(7.0);
		buy1.getdiscount().dodiscount(buy1.getcost());
		Buy buy2=new Buy(360.0);
		buy2.getdiscount().dodiscount(buy2.getcost());
		Buy buy3=new Buy(800.0);
		buy3.getdiscount().dodiscount(buy3.getcost());
}
}

运行结果:

例二.

Hand.java

java 复制代码
package 策略模式2;

public class Hand {
	public static final int HANDVALUE_GUU=0;
	public static final int HANDVALUE_COH=1;
	public static final int HANDVALUE_PAA=2;
	public static final Hand[] hand={
		new Hand(HANDVALUE_GUU),
		new Hand(HANDVALUE_COH),
		new Hand(HANDVALUE_PAA),
	};
	private static final String[] name={
	"石头","剪刀","布",
};
private int handvalue;
public Hand(int handvalue) {
	this.handvalue=handvalue;
}
public static Hand getHand(int handvalue){
	return hand[handvalue];
}
public boolean isStrongerthan(Hand h) {
	return fight(h)==1;
}
public boolean isWeakerthan(Hand h) {
	return fight(h)==-1;
}
private int fight(Hand h) {
	if(this==h) {
		return 0;
	}else if((this.handvalue+1)%3==h.handvalue) {
		return 1;
	}else return -1;
}
public String toString() {
	return name[handvalue];
}
}

Player.java

java 复制代码
package 策略模式2;
public class Player {
	private String name;
	private Strategy strategy;
	private int wincount;
	private int losecount;
	private int gamecount;
	public Player(String name,Strategy strategy) {
		this.name=name;
		this.strategy=strategy;
	}
	public Hand nexthand() {
		return strategy.nexthand();
	}
	public void win() {
		strategy.study(true);
		wincount++;
		gamecount++;
	}
	public void lose() {
		strategy.study(false);
		losecount++;
		gamecount++;
	}	
	public void even() {
		gamecount++;
	}
	public String tostring() {
		return "["+name+":"+gamecount+"games,"+wincount+"win,"+losecount+"lose."+"]";
	}
}

probstrategy.java

java 复制代码
package 策略模式2;
import java.util.Random;
public class Probstrategy implements Strategy {
	private Random random;
	private int prevhandvalue=0;
	private int currenthandvalue=0;
	private int [][]history= {
			{1,1,1},
			{1,1,1},
			{1,1,1},
	};
	public Probstrategy(int seed) {
		random=new Random(seed);
	}
	@Override
	public Hand nexthand() {
		// TODO Auto-generated method stub
		int bet=random.nextInt(getSum(currenthandvalue));
		return new Hand(bet);
	}

	private int getSum(int hv) {
		// TODO Auto-generated method stub
		int sum=0;
		for(int i=0;i<3;i++) {
			sum+=history[hv][i];
		}
		return sum;
	}
	@Override
	public void study(boolean win) {
		// TODO Auto-generated method stub
		if(win) {
			history[prevhandvalue][currenthandvalue]++;
		}
		else {
			history[prevhandvalue][(currenthandvalue+1)%3]++;
			history[prevhandvalue][(currenthandvalue+2)%3]++;

		}
	}

}

winstrategy.java

java 复制代码
package 策略模式2;
import java.util.Random;
public class Winningstrategy implements Strategy {
	private Random random;
private boolean won=false;
private Hand prevhand;
public Winningstrategy(int seed) {
	random=new Random(seed);
}
public Hand nexthand() {
	if(!won) {
		prevhand=Hand.getHand(random.nextInt(3));
	}
	return prevhand;
}
@Override
public void study(boolean win) {
	// TODO Auto-generated method stub
	won=win;
}
}

strategy.java

java 复制代码
package 策略模式2;

public interface Strategy {
public abstract Hand nexthand();
public abstract void study(boolean win);
}

Main.java

java 复制代码
package 策略模式2;

public class Main {
	public static void main(String[] args) {
		if(args.length!=2) {
			System.out.println("Usage java main randomseed1 randomseed2");
			System.out.println("Example :java Main 314 15");
			System.exit(0);
		}
		int seed1=Integer.parseInt(args[0]);
		int seed2=Integer.parseInt(args[1]);
Player player1=new Player("haha",new Winningstrategy(seed1));
Player player2=new Player("xixi",new Probstrategy(seed2));
for(int i=0;i<1000;i++) {
	Hand nexthand1=player1.nexthand();
	Hand nexthand2=player2.nexthand();
if(nexthand1.isStrongerthan(nexthand2)) {
	System.out.println("winner:"+player1);
	player1.win();
	player2.lose();
}else if(nexthand2.isStrongerthan(nexthand1)){
	System.out.println("winner:"+player2);
	player2.win();
	player1.lose();
}
else {
	System.out.println("even");
	player1.even();
	player2.even();
}
}
System.out.println("total resaults:");
System.out.println(player1.tostring());
System.out.println(player2.tostring());
	}
}

运行结果:

习题练习

习题10-1解析:

Random.java

java 复制代码
package 策略模式2;
import java.util.Random;
public class RadomStrategy implements Strategy{
	private Random random;
	public RadomStrategy(int seed) {
		random=new Random(seed);
	}
	@Override
	public Hand nexthand() {
		return Hand.getHand(random.nextInt(3));
	}

	@Override
	public void study(boolean win) {
		// TODO Auto-generated method stub
		
	}

}

Main.java

java 复制代码
package 策略模式2;

public class Main {
	public static void main(String[] args) {
		if(args.length!=3) {
			System.out.println("Usage java main randomseed1 randomseed2");
			System.out.println("Example :java Main 314 15 9");
			System.exit(0);
		}
		int seed1=Integer.parseInt(args[0]);
		int seed2=Integer.parseInt(args[1]);
		int seed3=Integer.parseInt(args[2]);
Player player1=new Player("haha",new Winningstrategy(seed1));
Player player2=new Player("xixi",new Probstrategy(seed2));
Player player3=new Player("hehe",new RadomStrategy(seed3));
for(int i=0;i<1000;i++) {
	Hand nexthand1=player1.nexthand();
	Hand nexthand2=player2.nexthand();
if(nexthand1.isStrongerthan(nexthand2)) {
	System.out.println("winner:"+player1);
	player1.win();
	player3.lose();
}else if(nexthand2.isStrongerthan(nexthand1)){
	System.out.println("winner:"+player2);
	player3.win();
	player1.lose();
}
else {
	System.out.println("even");
	player1.even();
	player3.even();
}
}
System.out.println("total resaults:");
System.out.println(player1.tostring());
System.out.println(player3.tostring());
	}
}

运行结果:

10-2解析:

10-3解析:

10-4解析:

Main.java

java 复制代码
public class Main {
public static void main(String[] args) {
	String[] data= {
			"Dumpty","Baba","Coco","Apple","Elements"
	};
	SortAndPrint sap=new SortAndPrint(data,new SelectionSorter());
	sap.execute();
}
}

SortAndPrint.java

java 复制代码
public class SortAndPrint {
Comparable[]data;
Sorter sorter;
public SortAndPrint(Comparable[] data,Sorter sorter) {
	this.data=data;
	this.sorter=sorter;
}
public void execute() {
	print();
	sorter.sort(data);
	print();
}
public void print() {
	for(int i=0;i<data.length;i++) {
		System.out.print(data[i]+",");
	}
	System.out.println("");
}
}

SelectionSorter.java(简单选择排序)

java 复制代码
public class SelectionSorter implements Sorter {

	@Override
	public void sort(Comparable[] data) {
		// TODO Auto-generated method stub
	for(int i=0;i<data.length-1;i++) {
		int min=i;
		for(int j=i+1;j<data.length;j++) {
			if(data[min].compareTo(data[j])>0) {
				min=j;
			}
		}
		Comparable passingplace=data[min];
		data[min]=data[i];
		data[i]=passingplace;
	}
	}

}

Sorter.java

java 复制代码
import java.lang.Comparable;
public interface Sorter {
public abstract void sort(Comparable[] data);
}

运行结果:

增加一个快速排序

Main.java

java 复制代码
public class Main {
public static void main(String[] args) {
	String[] data= {
			"Dumpty","Baba","Coco","Apple","Elements"
	};
	SortAndPrint sap=new SortAndPrint(data,new SelectionSorter());
	SortAndPrint qsort=new SortAndPrint(data,new QuickSorter());
//	sap.execute();
	System.out.println("快速排序");
	qsort.execute();
}
}

QuickSorter.java

java 复制代码
public class QuickSorter implements Sorter{
Comparable[] data;
	@Override
	public void sort(Comparable[] data) {
		// TODO Auto-generated method stub
		this.data=data;
		qsort(0,data.length-1);
		
	}
	private void qsort(int pre, int post) {
		// TODO Auto-generated method stub
		int saved_pre=pre;
		int saved_post=post;
		Comparable mid=data[(pre+post)/2];
		do {
			while(data[pre].compareTo(mid)<0) {
				pre++;
			}
			while(mid.compareTo(data[post])<0) {
				post--;
			}
			if(pre<=post) {
				Comparable tmp=data[pre];
				data[pre]=data[post];
				data[post]=tmp;
				pre++;
				post--;
			}
		}while(pre<=post);
		if(saved_pre<post) {
			qsort(saved_pre,post);
		}
		if(pre<saved_post) {
			qsort(pre,saved_post);
		}
	}

}

运行结果:

相关推荐
ThetaarSofVenice2 天前
电影院售票 - 策略模式(Strategy Pattern)
java·设计模式·策略模式
大包菜 cc3 天前
使用工厂+策略模式实现去除繁琐的if else
简单工厂模式·策略模式
蜗牛沐雨5 天前
使用 PyInstaller 和 hdiutil 打包 Tkinter 应用为 macOS 可安装的 DMG 文件
macos·策略模式
西海天际蔚蓝5 天前
使用策略模式时的一个生效问题
策略模式
zwh12984540605 天前
《C++设计模式》策略模式
c++·设计模式·策略模式
HEU_firejef5 天前
设计模式——策略模式
设计模式·策略模式
小馒头学python6 天前
PowerShell 常见问题解答
策略模式
冀晓武7 天前
C++ 设计模式:策略模式(Strategy Pattern)
c++·设计模式·策略模式
opentogether7 天前
中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern) 和 策略模式(Strategy Pattern)
桥接模式·策略模式·中介者模式