一、什么是设计模式
1.定义
作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有很多,可以选择Idea进行开发,也可以使用ec1ipse进行开发,也可以使用其他的一些开发工具。
小tips:单例模式+工厂模式+代理模式+模板+策略,可以解决很多问题
该模式定义了一系列算法(idea就是一个算法,eclipse也是一个算法,而这些算法都有一个共同的目标就是对代码进行开发,满减活动是一个算法、买一送一是一个算法、折上折活动也是一个算法,这些算法的目标就是促销活动的选择),并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户(客户就是程序员,也是我们的商场)。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任(程序员使用idea的底层算法进行开发)和算法的实现(iead底层封装了一系列的算法,eclipse底层封装了一系列的算法)分割开来,并委派给不同的对象对这些算法进行管理(策略模式里面有一个决策,是专门对这些对这些算法进行管理的,我们通过决策来选择使用哪个算法来实现我想要达到的一个目的)。
二、结构(主要角色)
1.抽象策略(strategy)类:这是一个抽象角色,通常由一个接口或抽象实现。此角色给出所有的具体策略类所需的接口。(idea底层的算法和eclipse底层的算法是不一样的,但是我们可以往上抽取出它的抽象方法这样就起到了一个规定的作用,不管底层用的是什么算法,我们最终的目的就是对代码进行开发)
2.具体策略(concrete strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。(就是idea和eclipse)
3.环境(Context)类:持有一个策略类的引用,最终给客户端调用。 (来选择使用哪个算法来实现我的目的)
三、案例
1.题目以及题目分析
一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:
促销活动就是我们具体的算法,根据不同的促销活动我们可以编写不同的算法。
2.类图分析
- 抽象策略(strategy)类:这是一个抽象角色,通常由一个接口或抽象实现。此角色给出所有的具体策略类所需的接口。(SalesA底层的算法、SalesB、SalesC底层的算法是不一样的,但是我们可以往上抽取出它的抽象方法这样就起到了一个规定的作用,不管底层用的是什么算法,我们最终的目的就是选择一种促销活动进行价格的计算)
Startegy抽象策略类,定义类了一个show方法,用来展示促销活动的内容,和一个calcPrice方法,用来计算促销后的价格,他下面有三个子实现类。
2.具体策略类:实现了抽象策略定义的接口,提供具体的算法实现或行为。(就是SalesA、SalesB、SalesC)Sales A、Sales B、Sales C三个子实现类就是具体的算法的封装,是具体策略类,都要求重写父类中的show方法和calaPrice方法,进行该促销活动信息的展示和价格计算。
3.环境(Context)类:持有一个策略类的引用,最终给客户端调用。 (来选择使用哪个算法来实现我的目的)SalesMan售卖员是环境(context)类,里面声明了一个策略类型的变量,这个变量是用来管理具体的策略算法的,提供有参的构造(注入)提供了一个策略对象的赋值,还可以写set get方法,salesManShow方法是促销员给客户展示促销活动,quote方法是进行价格的计算。
3.代码编写:
策略类:
package org.example.pattern.startegy;
//策略模式
//定义所有促销活动的抽象接口public interface Startegy {public double calcPrice(double goodsPrice);void show();
}
定义具体的策略算法类:
促销活动一:
package org.example.pattern.startegy;
//具体策略类,来封装算法
public class SalesA implements Startegy{@Overridepublic double calcPrice(double goodsPrice) {if (goodsPrice > 300){return goodsPrice - 100;}return goodsPrice;}@Overridepublic void show() {System.out.println("对于满减活动的促销活动(满300-100)");}
}
促销活动二 :
package org.example.pattern.startegy;public class SalesB implements Startegy{@Overridepublic double calcPrice(double goodsPrice) {return goodsPrice;}@Overridepublic void show() {System.out.println("买一送一,恭喜获得两个产品");}
}
促销活动三:
package org.example.pattern.startegy;public class SalesC implements Startegy{@Overridepublic double calcPrice(double goodsPrice) {return goodsPrice * 0.9 * 0.7;}@Overridepublic void show() {System.out.println("折上折活动,打九折再打7折");}
}
定义环境角色(context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员,聚合咱们的策略类。
package org.example.pattern.startegy;public class SalesMan {//聚合策略类对象,通过有参构造方法可以具体设置具体的策略类对象private Startegy startegy;public SalesMan(Startegy startegy) {this.startegy = startegy;}//set和get方法,方便设置和获取具体的策略类对象,//set方法可以动态设置具体的策略类对象//get方法可以获取具体的策略类对象public void setStartegy(Startegy startegy) {this.startegy = startegy;}public Startegy getStartegy() {return startegy;}//这里还有一个活动,促销员展示促销活动给用户public void SalesManShow(){//每一个具体的促销活动里面都有show方法,所以这里调用具体策略类对象的show方法startegy.show();}//这里还有一个活动,计算打折后的价格public double quote(double booksPrice){return this.startegy.calcPrice(booksPrice);}}
最后定义一个客户端类来展示
package org.example.pattern.startegy;public class Client {public static void main(String[] args) {// 创建上下文对象,即设置促销员的对象SalesMan salesMan = new SalesMan(new SalesA()); // 因为没有提供无参的构造方法,所以必须具体的促销活动salesMan.SalesManShow(); // 调用销售员展示促销活动的方法double quote = salesMan.quote(300);System.out.println("最终的价格为" + quote);System.out.println("----------");salesMan.setStartegy(new SalesB());salesMan.SalesManShow();double quote1 = salesMan.quote(300);System.out.println("最终的价格为" + quote);System.out.println("----------");salesMan.setStartegy(new SalesC());salesMan.SalesManShow();double quote2 = salesMan.quote(300);System.out.println("最终的价格为" + quote);}
}