大话设计模式之策略模式(结合简单工厂),程序完善过程蕴含智慧
2015-12-13 14:11
489 查看
不管你编程经验多么丰富,也很难一次性写出完美无瑕的程序,程序都是一步步完善出来的,完善的过程中蕴含中无穷的智慧与乐趣,随着你编程的时间增加,你写的程序会一次比一次好,但是前提是你要不断的思考,随着面向对象语言的流行,我们要学会使用面向对象的思想来编写程序,而不是使用面向过程的方式来编写程序,但是这也需要不断锤炼,只要不断思考,我们终究可以写出完全面向对象的程序!废话有点多,请原谅,接下来说重点,说一下设计模式中的策略模式!请细心看完,你会有收获的!
1.设计一个商场商品收费软件,这是简化的,可能我们不会想太多,就马上着手编写程序。
3.当我们写完这个程序的时候,依然有一种意犹未尽的感觉,因为一个主方法里面写了太多的代码,不利于控制和维护,看起来也乏力,如果此时需要又要改变的话,那就必须写该代码了,如是觉得要改善一下代码。
4.我们想到了使用简单工厂来封装对象的创建细节,进而是的程序的拓展性提高,也利于维护,但是细心一想,需求可能随时改变,就算利于维护,维护的工作量也很大,需求改变了,每次都要修改工厂的类,从而满足需求,如是想到了策略模式。
5.使用了策略模式,提供一个上下文,但是程序看起来不美观,如是结合简单工厂,晚上这个策略模式。
6.简单工厂的使用,不一定都是创建一个工厂,也可以通过构造方法的方式实现,此时我们的程序的拓展性、可重用型、可维护性都可以得到提高,现在即使有需求的变更,也不用怕了,例如现在需求要求增加一个“满700减200”的活动需求,这时候我们只需要在CashContext类的构造方法中增加一个case条件,再在main方法中增加一个选项即可!
1.设计一个商场商品收费软件,这是简化的,可能我们不会想太多,就马上着手编写程序。
package com.psc.construct.model.strategy; import java.util.Scanner; //商品收费 public class CashTest1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入商品单价:"); String priceStr = sc.next(); //读出商品单价 System.out.print("请输入商品数量:"); String number = sc.next(); //读出商品数量 try { double price = Double.valueOf(priceStr); double num = Double.valueOf(number); double totalPrice = price * num; System.out.println("总价格为:" + totalPrice); }catch(Exception e) { e.printStackTrace(); } } }2.写完这个程序的时候,我们心里就会有一种意犹未尽的感觉,不过也是,程序实在太简单,想一下,如果现在需要改变了,要求可以打折,此时我们之前编写的程序就要推到重新编写,这是一件很糟糕的thing。于是我们吸取教训,第二次完善一下程序。
package com.psc.construct.model.strategy; import java.util.Scanner; //商品收费(增加打折) public class CashTest2 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入商品单价:"); String priceStr = sc.next(); //读出商品单价 System.out.print("请输入商品数量:"); String number = sc.next(); //读出商品数量 System.out.println("收费类型如下:"); String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折"}; for (String temp : types) { System.out.println(temp); } System.out.print("请选择收费类型的序号:"); String priceFlag = sc.next(); try { double price = Double.valueOf(priceStr); double num = Double.valueOf(number); int flag = Integer.valueOf(priceFlag); double totalPrice = 0.0; switch(flag) { case 1 : totalPrice = price * num; break; case 2 : totalPrice = price * num * 0.8; break; case 3 : totalPrice = price * num * 0.7; break; case 4 : totalPrice = price * num * 0.5; break; default : throw new RuntimeException("没有此收费类型序号!"); } System.out.println("总价格为:" + totalPrice); }catch(NumberFormatException e) { e.printStackTrace(); }catch(Exception e) { e.printStackTrace(); } } }
3.当我们写完这个程序的时候,依然有一种意犹未尽的感觉,因为一个主方法里面写了太多的代码,不利于控制和维护,看起来也乏力,如果此时需要又要改变的话,那就必须写该代码了,如是觉得要改善一下代码。
package com.psc.construct.model.strategy; import java.util.Scanner; //商品收费(增加打折--简单工厂) public class CashTest3 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入商品单价:"); String priceStr = sc.next(); //读出商品单价 System.out.print("请输入商品数量:"); String number = sc.next(); //读出商品数量 System.out.println("收费类型如下:"); String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"}; for (String temp : types) { System.out.println(temp); } System.out.print("请选择收费类型的序号:"); String priceFlag = sc.next(); try { double price = Double.valueOf(priceStr); double num = Double.valueOf(number); int flag = Integer.valueOf(priceFlag); CashSuper cashSuper = CashFactory.createPriceInstance(flag); //简单工厂 double totalPrice = cashSuper.acceptPrice(price * num); System.out.println("总价格为:" + totalPrice); }catch(NumberFormatException e) { e.printStackTrace(); }catch(Exception e) { e.printStackTrace(); } } }
package com.psc.construct.model.strategy; public abstract class CashSuper { public abstract double acceptPrice(double money); }
package com.psc.construct.model.strategy; //正常收费 public class CashNormal extends CashSuper { @Override public double acceptPrice(double money) { return money; } }
package com.psc.construct.model.strategy; //打折 public class CashRebate extends CashSuper { private double rebate; public CashRebate(double rebate) { this.rebate = rebate; } @Override public double acceptPrice(double money) { return this.rebate * money; } }
package com.psc.construct.model.strategy; //满300送100 public class CashReturn extends CashSuper { private double fullPrice; private double sendPrice; public CashReturn(double fullPrice, double sendPrice) { this.fullPrice = fullPrice; this.sendPrice = sendPrice; } @Override public double acceptPrice(double money) { if (money >= fullPrice) { return money - sendPrice; } return money; } }
package com.psc.construct.model.strategy; public class CashFactory { public static CashSuper createPriceInstance(int flag) { CashSuper cashSuper; switch(flag) { case 1 : cashSuper = new CashNormal(); break; case 2 : cashSuper = new CashRebate(0.8); break; case 3 : cashSuper = new CashRebate(0.7); break; case 4 : cashSuper = new CashRebate(0.5); break; case 5 : cashSuper = new CashReturn(300, 100); break; default : throw new RuntimeException("没有此收费类型"); } return cashSuper; } }
4.我们想到了使用简单工厂来封装对象的创建细节,进而是的程序的拓展性提高,也利于维护,但是细心一想,需求可能随时改变,就算利于维护,维护的工作量也很大,需求改变了,每次都要修改工厂的类,从而满足需求,如是想到了策略模式。
package com.psc.construct.model.strategy; import java.util.Scanner; //商品收费(增加打折--策略模式) public class CashTest4 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入商品单价:"); String priceStr = sc.next(); //读出商品单价 System.out.print("请输入商品数量:"); String number = sc.next(); //读出商品数量 System.out.println("收费类型如下:"); String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"}; for (String temp : types) { System.out.println(temp); } System.out.print("请选择收费类型的序号:"); String priceFlag = sc.next(); try { double price = Double.valueOf(priceStr); double num = Double.valueOf(number); int flag = Integer.valueOf(priceFlag); CashContext cashContext; //收费的上下文 switch(flag) { case 1 : cashContext = new CashContext(new CashNormal()); break; case 2 : cashContext = new CashContext(new CashRebate(0.8)); break; case 3 : cashContext = new CashContext(new CashRebate(0.7)); break; case 4 : cashContext = new CashContext(new CashRebate(0.5)); break; case 5 : cashContext = new CashContext(new CashReturn(300, 100)); break; default : throw new RuntimeException("没有此收费类型序号!"); } double totalPrice = cashContext.getFinalPrice(price) * num; System.out.println("总价格为:" + totalPrice); }catch(NumberFormatException e) { e.printStackTrace(); }catch(Exception e) { e.printStackTrace(); } } }
package com.psc.construct.model.strategy; //定义一个上下文 public class CashContext { private CashSuper cashSuper; public CashContext(CashSuper cashSuper) { this.cashSuper = cashSuper; } public double getFinalPrice(double money) { //根据不同的收费策略取得不同的计算结果 return cashSuper.acceptPrice(money); } }
5.使用了策略模式,提供一个上下文,但是程序看起来不美观,如是结合简单工厂,晚上这个策略模式。
package com.psc.construct.model.strategy; import java.util.Scanner; //商品收费(增加打折--策略模式结合简单工厂) public class CashTest5 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("请输入商品单价:"); String priceStr = sc.next(); //读出商品单价 System.out.print("请输入商品数量:"); String number = sc.next(); //读出商品数量 System.out.println("收费类型如下:"); String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"}; for (String temp : types) { System.out.println(temp); } System.out.print("请选择收费类型的序号:"); String priceFlag = sc.next(); try { double price = Double.valueOf(priceStr); double num = Double.valueOf(number); int flag = Integer.valueOf(priceFlag); //收费的上下文 使用简单工厂封装创建对象过程 CashContext cashContext = new CashContext(flag); double totalPrice = cashContext.getFinalPrice(price * num); System.out.println("总价格为:" + totalPrice); }catch(NumberFormatException e) { e.printStackTrace(); }catch(Exception e) { e.printStackTrace(); } } }
package com.psc.construct.model.strategy; //定义一个上下文 public class CashContext { private CashSuper cashSuper; //通过构造方法,传入具体的收费策略 public CashContext(int flag) { //简单工厂 switch(flag) { case 1 : cashSuper = new CashNormal(); break; case 2 : cashSuper = new CashRebate(0.8); break; case 3 : cashSuper = new CashRebate(0.7); break; case 4 : cashSuper = new CashRebate(0.5); break; case 5 : cashSuper = new CashReturn(300, 100); break; default : throw new RuntimeException("没有此收费类型序号!"); } } public CashContext(CashSuper cashSuper) { this.cashSuper = cashSuper; } public double getFinalPrice(double money) { //根据不同的收费策略取得不同的计算结果 return cashSuper.acceptPrice(money); } }
6.简单工厂的使用,不一定都是创建一个工厂,也可以通过构造方法的方式实现,此时我们的程序的拓展性、可重用型、可维护性都可以得到提高,现在即使有需求的变更,也不用怕了,例如现在需求要求增加一个“满700减200”的活动需求,这时候我们只需要在CashContext类的构造方法中增加一个case条件,再在main方法中增加一个选项即可!
相关文章推荐
- leetcode -- Permutation Sequence -- 重点
- 下列代码可以将十进制转换为二进制、八进制和十六进制
- 程序员必须了解的内存知识
- Android UncaughtExceptionHandler捕获Crash
- 微信中 - 发现 - 界面的实现
- c++ 初始化 http://www.nowcoder.com/test/question/done?tid=2198842&qid=25454#summary
- Android ListView网络加载图片之内存缓存
- C/C++ 之 restrict关键字
- 设计模式C#实现(十二)——装饰模式
- 结合OPENSIFT源码详解SIFT算法
- 用哈希法组织关键字 2
- 对list排序的代码优化
- iOS开发之绝对布局和相对布局(屏幕适配)
- 【深入】java 单例模式
- 用哈希法组织关键字
- C 打印成绩及姓名
- APUE学习记录——进程环境
- JQuery中$.ajax()方法参数详解
- SSH设置别名访问远程服务器
- UVA 11549 Calculator Conundrum 题解