开发中常见的场景

  • JavaSE中GUI编程中的布局管理

  • Spring框架中,Resource接口,资源访问策略

  • javax.servlet.http.HttpServlet#service()

场景

  • 某个市场人员接到单后的报价策略(CRM系统中常见问题),报价策略很复杂,可以简单作如下分类:

    • 普通客户小批量的报价

    • 普通客户大批量的报价

    • 老客户小批量的报价

    • 老客户大批量的报价

  • 具体选用那个报价策略,这需要根据实际情况来确定.这时候,我们采用策略模式即可

  • 使用条件语句也可以处理,但是如果类型特别多,算法比较复杂时,整个条件控制代码会变得很长,难于维护

使用策略模式

策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决某一问题,同时可以方便的更换算法或者增加新的算法.并且由客户端决定调用那个算法

类图

QQ截图20161208100725.png

本质

分离算法,选择实现

Code

/**
 * 策略接口
 * @author Matrix42
 *
 */
public interface Strategy {
    public double getPrice(double standaPrice);

}
/**
 * 普通客户少量
 * @author Matrix42
 *
 */
public class NewCustomerFewStrategy implements Strategy{

    @Override
    public double getPrice(double standaPrice) {
        System.out.println("不打折!");
        return standaPrice;
    }

}
/**
 * 普通客户大量
 * @author Matrix42
 *
 */
public class NewCustomerManyStrategy implements Strategy{

    @Override
    public double getPrice(double standaPrice) {
        System.out.println("打九折!");
        return standaPrice*0.9;
    }

}
/**
 * 老客户少量
 * @author Matrix42
 *
 */
public class OldCustomerFewStrategy implements Strategy{

    @Override
    public double getPrice(double standaPrice) {
        System.out.println("打八五折!");
        return standaPrice*0.85;
    }

}
/**
 * 老客户大量
 * @author Matrix42
 *
 */
public class OldCustomerManyStrategy implements Strategy{

    @Override
    public double getPrice(double standaPrice) {
        System.out.println("打八折!");
        return standaPrice*0.8;
    }

}
/**
 * 负责和具体的策略类交互
 * 这样的话,具体的算法和直接的客户端调用分离了,使得算法可以独立于客户端独立额变化
 * 如果使用spring的依赖注入功能,还可以通过配置文件,动态的切换不同的算法
 * @author Matrix42
 *
 */
public class Context {
    //当前采用的算法对象
    private Strategy strategy;

    public Context(Strategy strategy) {
        super();
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void printPrice(double s){
        System.out.println("您的报价:"+strategy.getPrice(s));
    }

}
public class Client {

    public static void main(String[] args) {
        Strategy strategy = new OldCustomerFewStrategy();
        Context ctx = new Context(strategy);

        ctx.printPrice(998);
    }

}

我在项目中用到的一个时间转换类

public class DateToTimestamp implements Serializable {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        String time0 = "2016-11-19 12:28:12";
        String time1 = "2016-11-19 12:28:12.342412";
        String time2 = "2016-11-19";
        String time3 = "12:00:50.3";
        String time4 = "00:50.3";
        String time5 = "12:00:50";

        DateToTimestamp dt = new DateToTimestamp();
        System.out.println("time:" +dt.call(time0,"yyyyMMddHHmm"));
        System.out.println("time:" + dt.call(time1,2));
        System.out.println("time:" + dt.call(time2,0));
        System.out.println("time:" + dt.call(time3,1));
        System.out.println("time:" + dt.call(time4,0));
        System.out.println("time:" + dt.call(time5,1));

    }

    abstract class Algo {
        protected String timeString;
        protected SimpleDateFormat format;
        protected long time = 0L;

        public void setTimeString(String timeString) {
            this.timeString = timeString;
        }

        public void setFormat(SimpleDateFormat format) {
            this.format = format;
        }

        abstract long getTime();
    }

    class Match {
        private String timeString;
        private Pattern pattern;
        private Matcher matcher;
        private Algo algo;

        public Match(String timeString, Pattern pattern,SimpleDateFormat format, Algo algo) {
            this.timeString = timeString.trim();
            algo.setTimeString(timeString.trim());
            this.pattern = pattern;
            algo.setFormat(format);
            this.algo = algo;
        }

        public boolean isMatch() {
            matcher = pattern.matcher(timeString);
            return matcher.matches();
        }

        public long getTime() {
            return algo.getTime();
        }

    }

    /**
     * 自定义日期格式
     * @param timeString
     * @param formatString
     * @return formated time
     */
    public Long call(String timeString,String formatString){
        SimpleDateFormat format = new SimpleDateFormat(formatString);
        String  string = format.format(call(timeString,0));
        return Long.parseLong(string);

    }

    /**
     * 日期转换成毫秒
     * @param timeString
     * @return
     */
    public Long call(String timeString,final int length) {

        List<Match> mList = new ArrayList<Match>();

        // 匹配 年-月-日 时:分:秒.毫秒
        Pattern p1 = Pattern
                .compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}(\\.\\d+)?");
        SimpleDateFormat f1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Match m1 = new Match(timeString, p1, f1, new Algo() {

            @Override
            long getTime() {

                String[] times = timeString.split("\\.");
                try {
                    time += format.parse(times[0]).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (times.length == 2 && length!=0) {
                    int msLength = times[1].length();
                    if (msLength >= length) {
                        time += Long.parseLong(times[1].substring(0, length))*Math.pow(10, msLength-length);
                    } else {
                        time += Long.parseLong(times[1].substring(0, msLength));
                    }
                }
                return time;
            }
        });
        mList.add(m1);

        // 匹配 年-月-日
        Pattern p2 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
        SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd");
        Match m2 = new Match(timeString, p2, f2, new Algo() {

            @Override
            long getTime() {
                try {
                    time = format.parse(timeString).getTime();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return time;
            }
        });
        mList.add(m2);

        // 匹配 时:分:秒.毫秒
        Pattern p3 = Pattern.compile("\\d{2}:\\d{2}:\\d{2}(\\.\\d*)?");
        SimpleDateFormat f3 = new SimpleDateFormat("HH:mm:ss");
        Match m3 = new Match(timeString, p3, f3, new Algo() {

            @Override
            long getTime() {

                String[] times = timeString.split("[:.]");
                time += Long.parseLong(times[0]) * 60 * 60 * 1000;
                time += Long.parseLong(times[1]) * 60 * 1000;
                time += Long.parseLong(times[2]) * 1000;

                if (times.length == 4 && length != 0) {
                    int msLength = times[3].length();
                    if (msLength >= length && length!=0) {
                        time += Long.parseLong(times[3].substring(0, length))*Math.pow(10, msLength-length);
                    } else {
                        time += Long.parseLong(times[3].substring(0, msLength));
                    }
                }
                return time;
            }
        });
        mList.add(m3);

        // 匹配 分:秒.毫秒
        Pattern p4 = Pattern.compile("\\d{2}:\\d{2}(\\.\\d*)?");
        SimpleDateFormat f4 = new SimpleDateFormat("mm:ss");
        Match m4 = new Match(timeString, p4, f4, new Algo() {

            @Override
            long getTime() {
                String[] times = timeString.split("[:.]");
                time += Long.parseLong(times[0]) * 60 * 1000;
                time += Long.parseLong(times[1]) * 1000;

                if (times.length == 3 && length!=0) {
                    int msLength = times[2].length();
                    if (msLength >= length) {
                        time += Long.parseLong(times[2].substring(0, length))*Math.pow(10, msLength-length);
                    } else {
                        time += Long.parseLong(times[2].substring(0, msLength));
                    }
                }
                return time;
            }
        });
        mList.add(m4);

        for (Match match : mList) {
            if (match.isMatch()) {
                return match.getTime();
            }
        }

        throw new RuntimeException("时间格式不匹配!");
    }

    public Long call() {
        return 0001L;
    }

}