zoukankan      html  css  js  c++  java
  • 设计模式——策略模式

    一、引言

      十一黄金周,对于像我们这些屌丝来说,确实是个不错的出游时机,可惜的就是这个假期是public的,并不是我等屌丝独占的。真是有种生前活在人堆里的感慨,这时候选择交通工具是异常的重要,笔者回家需要经过深汕高速,每逢节假日,高速基本都会成为免费停车场的,加之国庆免费,真是雪上加霜啊。今天我所写的就是以选择交通工具为题阐述一下策略模式吧。

    二、策略模式

      1. 定义:定义一组算法,将每个算法都封装起来,并使他们之间可以互换。

      2. 类图:【如下图所示】

      3. 类图说明:

        3.1 ITransport:策略抽象类,定义每个算法必须具有的方法和属性。    

        3.2 Plane,Train,Car:策略中一组算法。

        3.3 Context:上下文角色,封装算法提供客户端调用的。    

    三、策略示例代码

      1. 策略抽象类

    package com.pattern.stratgy.core;
    
    /**
     * 策略接口——交通工具
     * @author yemaoan
     *
     */
    public interface ITransport {
        
        void buyTicket();
    }

      2. 具体策略(算法)

        2.1 选择火车

    package com.pattern.stratgy.core;
    
    public class Train implements ITransport {
    
        @Override
        public void buyTicket() {
            System.out.println("选择坐火车,硬座还比较划算");
    
        }
    
    }

        2.2 选择飞机

    package com.pattern.stratgy.core;
    
    public class Plane implements ITransport {
    
        @Override
        public void buyTicket() {
            System.out.println("选择坐飞机吧,快速,便捷,关键啊,是不会塞车...");
    
        }
    
    }

        2.3 选择汽车

    package com.pattern.stratgy.core;
    
    public class Car implements ITransport {
    
        @Override
        public void buyTicket() {
            System.out.println("选择坐汽车,堵就堵吧");
    
        }
    
    }

       3. Context封装角色

    package com.pattern.stratgy.core;
    
    /**
     * 封装角色
     * @author yemaoan
     *
     */
    public class Context {
    
        private ITransport transport;
        
        public Context(ITransport transport) {
            this.transport = transport;
        }
        
        public void buyTicket() {
            this.transport.buyTicket();
        }
    }

      4. JunitTest

    package com.pattern.strategy.test;
    
    import org.junit.Test;
    
    import com.pattern.stratgy.core.Context;
    import com.pattern.stratgy.core.ITransport;
    import com.pattern.stratgy.core.Train;
    
    public class TestStrategy {
    
        @Test
        public void testStrage() {
            //平生就差火车,动车没坐过了,让我也过一下火车瘾吧
            ITransport transport = new Train();        //生成策略对象,这样Client就知道得太多了,不应该啊,这是病,得医~
            Context context = new Context(transport);
            context.buyTicket();
        }
    }

    四、策略改进方法

      其实单纯的策略模式的弊病已经在上面的代码中表现得很明显了,在客户端调用时已经把当前的策略暴露出去了,怎么解决?让工厂帮一下忙吧,让我们看一下下面的一段代码。

      1. 策略工厂

    package com.pattern.stategy.factory;
    
    import com.pattern.stratgy.core.ITransport;
    
    /**
     * 设计模式老朋友了——策略工厂类
     * @author yemaoan
     *
     */
    public class StrategyFactory {
    
        public static <T extends ITransport> T getTransport(Class<T> cls) {
            ITransport transport = null;
            try {
                transport = (ITransport) Class.forName(cls.getName()).newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return (T) transport;
        }
        
        public static <T extends ITransport> T getTransport(String code) {
            return (T) getTransport(new ContentService().get(code));
        }
    }

      2. 算法值映射类

    package com.pattern.stategy.factory;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import com.pattern.stratgy.core.Car;
    import com.pattern.stratgy.core.Plane;
    import com.pattern.stratgy.core.Train;
    
    /**
     * 算法映射
     * @author yemaoan
     *
     */
    public class ContentService {
    
        private Map<String, Class> contentMap = new HashMap<String, Class>();
        
        public ContentService() {
            contentMap.put("train", Train.class);
            contentMap.put("plane", Plane.class);
            contentMap.put("car", Car.class);
        }
        
        public Class get(String key) {
            return contentMap.get(key);
        }
    }

      3. JunitTest【Client】

    package com.pattern.strategy.test;
    
    import org.junit.Test;
    
    import com.pattern.stategy.factory.StrategyFactory;
    import com.pattern.stratgy.core.Context;
    import com.pattern.stratgy.core.ITransport;
    import com.pattern.stratgy.core.Train;
    
    public class TestStrategy {
    
        @Test
        public void testStrage() {
            //平生就差火车,动车没坐过了,让我也过一下火车瘾吧
            ITransport transport = new Train();        //生成策略对象,这样Client就知道得太多了,不应该啊,这是病,得医~
            Context context = new Context(transport);
            context.buyTicket();
        }
        
        @Test
        public void testStrategy() {
            ITransport transport = StrategyFactory.getTransport("train");    //让工厂模式帮了我一把
            Context context = new Context(transport);
            context.buyTicket();
        }
    }

    五、总结

      1. 本文是对策略模式的一个阐述,策略其实也算是一个比较好理解的模式吧。当然单纯的使用策略模式是不太现实的,因为它会把算法完全的暴露给调用者,兵家之大忌啊。

      2. 针对策略模式的一些不足,笔者采用了工厂模式去解决,使得客户端调用时,只需要根据特定的code来获取相应的算法策略,而避免直接new算法策略。

  • 相关阅读:
    进程的实践与练习2
    士兵队列训练问题
    大数相加
    Ignatius and the Princess II
    Parentheses Balance (括号平衡)---栈
    简单计算器
    C++全排列函数next_permutation()和prev_permutation()
    黑白图像
    9*9乘法表
    输入5 个数按从小到大的顺序输出
  • 原文地址:https://www.cnblogs.com/maoan/p/3352891.html
Copyright © 2011-2022 走看看