设计模式——策略模式 & 单例模式
策略模式:
?* 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,
?* 不会影响到使用算法的客户。
?*
?* 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是
?* 实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合
?
单例模式:
?* 单例模式:
?* 单例类只能有一个实例
?* 单例类必须自己创建自己唯一的实例
?* 单例类必须给其他对象提供这一实例
?
策略模式实例:商场有不同打折促销方式,计算用户购买东西花费的钱。
CashSuper类:
package cn.edu.tju.strategyPattern;public class CashSuper {/* * 参数money为正常的,单价*件数 */public double acceptCash(double money){return 0;}}?
CashNormal类:
package cn.edu.tju.strategyPattern;/* * 正常付款方式,付款金额=单价*件数 */public class CashNormal extends CashSuper{public double acceptCash(double money){return money;}}?
CashRebate类:
package cn.edu.tju.strategyPattern;/* * 打折促销方式,付款金额=单价*件数*折扣 * 参数money为单价*件数,rebate为折扣 */public class CashRebate extends CashSuper{double rebate = 1;public CashRebate(double rebate){this.rebate = rebate;}public double acceptCash(double money){return money * rebate;}}?
CashReturn类:
package cn.edu.tju.strategyPattern;/* * 满多少A送多少B促销方式,付款金额 = (单价*件数 )- ((单价*件数)/ A) * B * 参数money = 单价*件数,moneyCondition表示满多少,moneyReturn表示返多少 */public class CashReturn extends CashSuper {private double moneyCondition = 0;private double moneyReturn = 0;public CashReturn(double moneyCondition, double moneyReturn) {this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}public double acceptCash(double money) {if (money >= moneyCondition) {return money - Math.floor((money / moneyCondition)) * moneyReturn;// floor向下取整} else {return money;}}}?
CashContext类:有多个CashSuper类属性,所以为聚合关系
package cn.edu.tju.strategyPattern;public class CashContext {private CashSuper cs;public CashContext(CashSuper cs){this.cs = cs;}public double getResult(double money){return cs.acceptCash(money);}}
?测试类:
package cn.edu.tju.strategyPattern;/* * 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化, * 不会影响到使用算法的客户。 * * 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是 * 实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合 */public class Test {/* * 条件判断语句又回到了客户端,每次增加新的促销方式时,需要修改客户端,添加新的促销算法类 * 为此,将策略模式和简单工厂模式相结合,具体看CashContext2以及Test2; * */public static void main(String[] args){double totalPrice = 0;//总额double price = 100;//单价int num = 5;//数量CashContext cc = null;//java中switch后的判断条件只能是char,int,short,byte类型,不能是stringint type = 3;//1表示正常,2表示打折,3表示返利switch(type){case 1:cc = new CashContext(new CashNormal());break;case 2:cc = new CashContext(new CashRebate(0.8));//打八折break;case 3:cc = new CashContext(new CashReturn(300, 100));//满300返100break;}double money = price * num;totalPrice = cc.getResult(money);System.out.println("The totalPrice is " + totalPrice);}}
?至此,策略模式完成。
这样存在问题:
??? ?* 条件判断语句又回到了客户端,每次增加新的促销方式时,需要修改客户端,添加新的促销算法类
??? ?* 为此,将策略模式和简单工厂模式相结合,具体看CashContext2以及Test2;
??? ?*
? 策略模式+简单工厂模式:
CashContext2类:
package cn.edu.tju.strategyPattern;/* * 条件判断语句又回到了客户端,每次增加新的促销方式时,需要修改客户端,添加新的促销算法类 * 为此,将策略模式和简单工厂模式相结合,具体看CashContext2以及Test2; * */public class CashContext2 {//private CashContext cs;private CashSuper cs;public CashContext2(int type){switch(type){case 1://正常收费this.cs = new CashNormal();break;case 2://打八折 this.cs = new CashRebate(0.8);break;case 3://满300返100this.cs = new CashReturn(300, 100);break;}}public double getResult(double money){return cs.acceptCash(money);}}?
Test2类:
package cn.edu.tju.strategyPattern;public class Test2 {/* * 条件判断语句又回到了客户端,每次增加新的促销方式时,需要修改客户端,添加新的促销算法类 * 为此,将策略模式和简单工厂模式相结合,具体看CashContext2以及Test2; * 这样将分支条件挪到了CashContext里,增加新的促销方式时,不再需要修改客户端,实现客户端与后台的完全分离 * */public static void main(String[] args){double totalPrice = 0;//总额double price = 100;//单价int num = 5;//数量//java中switch后的判断条件只能是char,int,short,byte类型,不能是stringint type = 1;//1表示正常,2表示打折,3表示返利CashContext2 cc = new CashContext2(type);totalPrice = cc.getResult(price * num);System.out.println("The total price is " + totalPrice);}}
?
?
单例模式
饿汉式:
package cn.edu.tju.singletonPattern;/* * 饿汉式单例模式:在自己被加载时就将自己实例化 * 提前占用系统资源 */public class EagerSingleton {//静态初始化,在类加载时即实例化,并只加载一次,解决了多线程问题private static EagerSingleton singleton = new EagerSingleton();/* * private的构造方法保证外部类不能通过new产生新的实例 */private EagerSingleton(){}/* * 提供一个public接口,允许外部类获得实例 */public static EagerSingleton getInstance(){return singleton;}}
?
?懒汉式:
package cn.edu.tju.singletonPattern;/* * 懒汉式单例模式,只有在第一次被引用时,才将自己实例化 * 锁占用资源 */public class LazySingleton {private static LazySingleton singleton = null;/* * private的构造方法保证外部类不能通过new产生新的实例 */private LazySingleton(){}/* * 提供一个public接口,允许外部类获得实例 * 为保证线程安全,即两个线程同时访问时不会得到两个实例,使用synchronized */public synchronized static LazySingleton getInstance(){if(singleton == null){singleton = new LazySingleton();}return singleton;}}?
测试类:
package cn.edu.tju.singletonPattern;/* * 单例模式: * 单例类只能有一个实例 * 单例类必须自己创建自己唯一的实例 * 单例类必须给其他对象提供这一实例 */public class Test {public static void main(String[] args){//饿汉式单例模式EagerSingleton singleton1 = EagerSingleton.getInstance();EagerSingleton singleton2 = EagerSingleton.getInstance();if(singleton1 == singleton2){//判断是否为同一内存地址System.out.println("它们是同一实例");}else{System.out.println("它们不是同一实例");}//懒汉式单例模式LazySingleton singleton3 = LazySingleton.getInstance();LazySingleton singleton4 = LazySingleton.getInstance();if(singleton3 == singleton4){//判断是否为同一内存地址System.out.println("它们是同一实例");}else{System.out.println("它们不是同一实例");}}}
?