一.策略模式是什么
策略模式是一种行为型对象模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换。这样,算法可以独立于使用它的客户端而变化。
策略者模式的核心思想是将一系列的算法封装到一系列的策略类里,作为一个抽象策略类的子类。具体策略角色包装了相关的算法或行为,而环境角色持有一个策略类的引用,这样可以在不影响到客户端的情况下更换算法。
策略者模式的优点在于它使得算法可以在不影响到客户端的情况下发生变化。通过将算法封装到独立的类中,并使它们具有共同的接口,策略者模式允许在运行时选择不同的算法实现,从而提高了程序的灵活性和可扩展性
二.类图
三.实例
示例一:
商场打折,一共有两种策略,满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);
}
}
}