一、委派模式
1.1、定义
委派模式不属于GOF23中设计模式中。委派模式的基本作用就是负责任务的调用和分配任务,和代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,二委派模式注重结果。spring中DispatcherServlet其实就是委派模式。
1.2、实例
老板boos给项目经理leader下达任务,项目经理会根据实际情况给每个员工派发任务,待员工把工资任务完成之后,再由项目经理汇报工资进度和结果给老板。
Iemployee员工接口
/**
* <p>
* 委派模式
* 员工接口
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public interface IEmployee {
public void doing(String command);
}
A类员工
/**
* <p>
* 委派模式:A类员工
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class EmployeeA implements IEmployee{
@Override
public void doing(String command) {
System.out.println("我是员工A,我现在开始干" + command + "工作");
}
}
B类员工
/**
* <p>
* 委派模式:A类员工
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class EmployeeB implements IEmployee{
@Override
public void doing(String command) {
System.out.println("我是员工B,我现在开始干" + command + "工作");
}
}
项目经理leader
/**
* <p>
* 委派模式:领导,员工的领导
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class Leader implements IEmployee{
private Map<String,IEmployee> targets = new HashMap<String, IEmployee>();
public Leader(){
targets.put("加密",new EmployeeA());
targets.put("登录",new EmployeeB());
}
//项目经理自己不干活
@Override
public void doing(String command) {
targets.get(command).doing(command);
}
}
老板boss
/**
* <p>
* 委派模式:老板
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class Boss {
public void command(String command,Leader leader){
leader.doing(command);
}
}
test
/**
* <p>
* 委派模式
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class DelegateTest {
public static void main(String[] args) {
//客户请求(Boss)、委派者(Leader)、被被委派者(Target)
//委派者要持有被委派者的引用
//代理模式注重的是过程, 委派模式注重的是结果
//策略模式注重是可扩展(外部扩展),委派模式注重内部的灵活和复用
//委派的核心:就是分发、调度、派遣
//委派模式:就是静态代理和策略模式一种特殊的组合
new Boss().command("登录",new Leader());
}
}
SpringMvc中的DispatcherServlet
委派模式和策略模式的综合应用模拟
其中还包含单例模式,工厂模式
/**
* <p>
* 模拟SpringMvc的DispatcherServlet
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class SimulationDispatcherServlet extends HttpServlet {
/**
* <servlet>
* <servlet-name>delegateServlet</servlet-name>
* <servlet-class>com.gupaoedu.vip.pattern.delegate.mvc.DispatcherServlet</servlet-class>
* <load-on-startup>1</load-on-startup>
* </servlet>
*
* <servlet-mapping>
* <servlet-name>delegateServlet</servlet-name>
* <url-pattern>/*</url-pattern>
* </servlet-mapping>
*/
//委派模式和策略模式的综合应用
private List<Handler> handlerMapping= new ArrayList<Handler>();
@Override
public void init() throws ServletException {
try {
/*Class<?> memberControllerClass = MemberController.class;
handlerMapping.add(new Handler()
.setController(memberControllerClass.newInstance())
.setMethod(memberControllerClass.getMethod("getMemberById", new
Class[]{String.class}))
.setUrl("/web/getMemberById.json"));*/
}catch (Exception e){
e.printStackTrace();
}
}
private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception{
//1、获取用户请求的url
// 如果按照J2EE 的标准、每个url 对对应一个Serlvet,url 由浏览器输入
String uri = request.getRequestURI();
//2、Servlet 拿到url 以后,要做权衡(要做判断,要做选择)
// 根据用户请求的URL,去找到这个url 对应的某一个java 类的方法
//3、通过拿到的URL 去handlerMapping(我们把它认为是策略常量)
Handler handle = null;
for (Handler h: handlerMapping) {
if(uri.equals(h.getUrl())){
handle = h;
break;
}
}
//4、将具体的任务分发给Method(通过反射去调用其对应的方法)
Object object = null;
try {
object =
handle.getMethod().invoke(handle.getController(),request.getParameter("mid"));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//5、获取到Method 执行的结果,通过Response 返回出去
// response.getWriter().write();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
doDispatch(req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
public static class Handler{
private Object controller;
private Method method;
private String url;
public Object getController() {
return controller;
}
public void setController(Object controller) {
this.controller = controller;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
二、策略模式
2.1、定义
策略模式是指定义了算法加载、分别封装起来,让他们自己可以互相替换,此模式让算法的变化不会影响到使用算法的用户。
2.2、应用场景
加入系统中有很多类,而他们的区别仅仅在于他们的行为不同
一个系统需要动态的在几种算法中选择一种
2.3、实例
促销策略
促销策略接口或抽象
/**
* <p>
* 促销策略抽象
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public interface IPromotionStrategy {
void doPromotion();
}
促销策略之无优惠
/**
* <p>
* 无优惠
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class EmptyStrategyI implements IPromotionStrategy {
@Override
public void doPromotion() {
System.out.println("无促销活动");
}
}
促销策略之优惠券抵扣策略
/**
* <p>
* 优惠券抵扣策略
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class CouponStrategyI implements IPromotionStrategy {
@Override
public void doPromotion() {
System.out.println("领取优惠券,课程的价格直接减优惠券面值抵扣");
}
}
促销策略之返现活动
/**
* <p>
* 返现活动
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class CashBackStrategyI implements IPromotionStrategy {
@Override
public void doPromotion() {
System.out.println("返现促销,返回的金额转到支付宝账号");
}
}
促销策略之拼团优惠策略
/**
* <p>
* 拼团优惠策略
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class GroupBuyStrategyI implements IPromotionStrategy {
@Override
public void doPromotion() {
System.out.println("拼团,满20 人成团,全团享受团购价");
}
}
优惠活动类,相当于代理类,内部实现对外隐藏,再来一个无参的方法(默认策略)就完美了
/**
* <p>
* 优惠活动
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class PromotionActivity {
private IPromotionStrategy IPromotionStrategy;
public PromotionActivity(IPromotionStrategy IPromotionStrategy) {
this.IPromotionStrategy = IPromotionStrategy;
}
public void execute(){
IPromotionStrategy.doPromotion();
}
}
促销策略工厂,简化使用难度,隐藏内部实现
/**
* <p>
* 促销策略工厂
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class PromotionStrategyFactory {
private static Map<String, IPromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String,
IPromotionStrategy>();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.COUPON,new CouponStrategyI());
PROMOTION_STRATEGY_MAP.put(PromotionKey.CASHBACK,new CashBackStrategyI());
PROMOTION_STRATEGY_MAP.put(PromotionKey.GROUPBUY,new GroupBuyStrategyI());
}
private static final IPromotionStrategy NON_PROMOTION = new EmptyStrategyI();
private PromotionStrategyFactory(){}
public static IPromotionStrategy getPromotionStrategy(String promotionKey){
IPromotionStrategy IPromotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return IPromotionStrategy == null ? NON_PROMOTION : IPromotionStrategy;
}
private interface PromotionKey{
String COUPON = "COUPON";
String CASHBACK = "CASHBACK";
String GROUPBUY = "GROUPBUY";
}
}
策略模式测试类
/**
* <p>
* 策略模式测试类
* </p>
*
* @author: longWarren
* @time: 2020/08/31
*/
public class StrategyTest {
public static void main(String[] args) {
String promotionKey = "GROUPBUY";
PromotionActivity promotionActivity = new
PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
promotionActivity.execute();
}
}
这个策略模式是说,要促销,但怎促销并不知道,PromotionActivity是促销的入口,但是怎么促销是个问题,需要提供促销类或者通过别的方式指定促销类
2.4策略模式在JDK中的应用
Comparator就是策略模式,比较器是一个策略,实现Comparator接口就可以,但是要比较策略却是未知的,需要客户提供或者指明。