写在前面:本人最近在看《大话设计模式》这本书,书里是用C#讲解的实例。现在写心得笔记与大家分享,就试着写一个JAVA版的。例子还是书里的例子。不过是Java语言实现的。后面也会给出本人的一些理解建议。谢谢《大话设计模式》的作者。
一、什么事策略模式?
策略模式,顾名思义就是对策略封装的一种模式。什么是策略,策略就是策略。在程序里就体现为程序的灵魂算法,不同的算法就是不同的策略。策略模式主要是针对算法的决策模式。上一篇的简单工厂模式主要是对对象分发的一种模式。
二、应用于什么情况?
多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为;
需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现;
对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
三、实例来袭(超市收银)。
超市是怎么收银的?扫你买的商品,系统根据商品的价格和数量进行计算总和,最后得出一共多少money。这是再简单不过的了,会有什么模式?有,当然有。假如超市庆十一,搞打折活动,收银系统会对产品进行打折计算;你可能想到是不是到双十一会不会有返利,是的,会有的。老是有这种活动是不是很头疼?系统要不同的改动。好烦。那咱们就可以用到我们伟大的设计模式,策略模式。
同样,既然是超市收银,它收的是商品的钱,咱们需要一个商品类Goods。一个主类用于交互Main类。策略模式,那咱们先定义一个总的策略抽象类Strategy,然后再定义一些策略实现类,本文只有两个策略,一个是折扣策略DiscountStrategy,一个是返利策略ReturnStrategy。然后还需要一个对策略配置的类,这个是本文的关键,但他没有什么代码,只是一个形式而已,Context上下文类。在Context类中,咱们需要先配置策略,然后提供用户调用策略接口。呵呵,是不是想到了什么?配置策略,其实就是对象的分发,那咱们就可以用到之前的工厂模式了。再加一个工厂类,StrategyFactory。
懂了么?看来是不懂了。那就继续。先不要晕,晕了也没事,再晕一会就会了。
代码驾到:
Main.java
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Goods[] goods = { new Goods("杯子", 9.9f, 1), new Goods("笔芯", 1f, 6),
new Goods("书包", 199f, 1) };
Context context1 = new Context("打折");
context1.configure(goods);
Context context2 = new Context("返送");
context2.configure(goods);
}
}
Goods.java
public class Goods {
private String name;
private float price;
private int num;
public Goods() {
}
public Goods(String name, float price, int num) {
this.name = name;
this.price = price;
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
Strategy.java
public abstract class Strategy {
/**
* 放置策略的抽象类,本程序只有一个策略接口
*/
public abstract void algorithm(Goods[] goods);
}
DiscountStrategy.java
public class DiscountStrategy extends Strategy {
private float rate;
public DiscountStrategy(float rate) {
this.rate = rate;
}
public void algorithm(Goods[] goods) {
// TODO Auto-generated method stub
float total = 0;
for (int i = 0; i < goods.length; i++) {
float sum = goods[i].getPrice() * goods[i].getNum() * rate;
total += sum;
System.out.println("商品" + i + "-[" + goods[i].getName() + "]\t单价:"
+ goods[i].getPrice() + "\t数量:" + goods[i].getNum()
+ "\t折率" + rate + "\t共:" + sum);
}
System.out.println("总计:" + total);
}
}
ReturnStratergy.java
public class ReturnStrategy extends Strategy {
private float limit;// 满多少
private float money;// 送多少
public ReturnStrategy(float limit, float money) {
this.limit = limit;
this.money = money;
}
public void algorithm(Goods[] goods) {
// TODO Auto-generated method stub
float total = 0;
for (int i = 0; i < goods.length; i++) {
float sum = goods[i].getPrice() * goods[i].getNum();
total += sum;
System.out.println("商品" + i + "-[" + goods[i].getName() + "]\t单价:"
+ goods[i].getPrice() + "\t数量:" + goods[i].getNum()
+ "\t共:" + sum);
}
if (total >= limit) {
total -= money;
System.out.println("满" + limit + "送" + money);
}
System.out.println("总计:" + total);
}
}
StrategyFactory.java
public class StrategyFactory {
public static Strategy createStrategy(String string) {
Strategy strategy = null;
if ("打折".equals(string)) {
strategy = new DiscountStrategy(0.8f);
} else if ("返送".equals(string)) {
strategy = new ReturnStrategy(200f, 50f);
}
return strategy;
}
}
Context.java
public class Context {
private Strategy strategy;
public Context(String string) {
this.strategy = StrategyFactory.createStrategy(string);
}
public void configure(Goods[] goods) {
strategy.algorithm(goods);
}
}
懂了么?还不懂?那就把代码咱贴上去运行一下你就明白了。
四、小结和建议
策略模式只是对策率的一种分配,看似和简单工厂模式很像,但他俩真的是没关系,请注意,简单工厂模式一般都是返回一个实例,而策略模式的Context类是对策略的配置和执行。其实有没有关系也没关系了,使用设计模式就是为了代码的“高内聚,低耦合”,为了代码“可复用”,“可扩展”,“易维护”,“灵活多变”而已。
对于本程序,只是对所有商品都进行了策略,实际上是针对不同的商品有不同的策略,此时应该怎么解决呢?我感觉,可以把策略放到商品里,因为策略是针对商品的,让每个商品都有一个策略的属性。这样可以实现
还有就是在各个策略里计算时,代码大同小异,那又该怎么优化呢?