设计模式11,迭代器模式、策略模式、解释器模式

目录

迭代器模式

策略模式

解释器模式


迭代器模式

提供一种方法,顺序访问一个集合对象的各个元素,又不暴露该对象的内部表示。简单来说就是遍历。

类型:行为型

使用场景:访问一个集合对象的内容而无需暴露它的内部表示。为遍历不同的集合结构提供一个统一的接口。

优点:分离了集合对象的遍历行为。

缺点:类的个数成对增加。

例子:

public class Game {
    private String name;

    public String getName() {
        return name;
    }

    public Game(String name) {

        this.name = name;
    }
}
public interface GameIterator {
    Game nextGame();
    boolean hasNextGame();
}
public class GameIteratorImpl implements GameIterator {
    private List gameList;
    int position;
    Game game;

    public GameIteratorImpl(List gameList) {
        this.gameList = gameList;
    }

    @Override
    public Game nextGame() {
        System.out.println("返回游戏,位置是:" + position);
        game = (Game) gameList.get(position);
        position ++;
        return game;
    }

    @Override
    public boolean hasNextGame() {
        if(position < gameList.size()){
            return true;
        }
        return false;
    }
}
public interface GameAggregate {
    void addGame(Game game);
    void removeGame(Game game);

    GameIterator getGameIterator();
}
public class GameAggregateImpl implements GameAggregate {

    private List gameList;

    public GameAggregateImpl(List gameList) {
        this.gameList = gameList;
    }

    @Override
    public void addGame(Game game) {
        gameList.add(game);
    }

    @Override
    public void removeGame(Game game) {
        gameList.remove(game);
    }

    @Override
    public GameIterator getGameIterator() {
        return new GameIteratorImpl(gameList);
    }
}
public class Test {
    public static void main(String[] args) {
        Game game1 = new Game("魔兽世界");
        Game game2 = new Game("炉石传说");
        Game game3 = new Game("超级玛丽");
        Game game4 = new Game("生化危机");
        Game game5 = new Game("节奏光剑");
        Game game6 = new Game("寂静岭");
        Game game7 = new Game("古墓丽影");

        GameAggregate gameAggregate = new GameAggregateImpl(new ArrayList());

        gameAggregate.addGame(game1);
        gameAggregate.addGame(game2);
        gameAggregate.addGame(game3);
        gameAggregate.addGame(game4);
        gameAggregate.addGame(game5);
        gameAggregate.addGame(game6);
        gameAggregate.addGame(game7);

        System.out.println("=====游戏列表======");
        printGames(gameAggregate);

        gameAggregate.removeGame(game1);
        gameAggregate.removeGame(game4);

        System.out.println("=====删除后的游戏列表======");
        printGames(gameAggregate);
    }

    private static void printGames(GameAggregate gameAggregate){
        GameIterator gameIterator = gameAggregate.getGameIterator();
        while (gameIterator.hasNextGame()){
            Game game = gameIterator.nextGame();
            System.out.println(game.getName());
        }
    }
}

看下类图:

 

关于迭代器模式,看代码结构其实很简单。一般都是使用,自己写的情况比较少。

用到设计模式的源码:

Iterator接口,他的实现类非常多,看一下ArrayList中内部类Itr。

再看一个,DefaultCursor


策略模式

定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到应用层。在实际的应用中可以大范围的处理掉if...else...

类型:行为型

使用场景:系统有很多类,而他们的区别仅仅在于行为不同。一个系统需要动态的在几个算法中选择一种。

优点:开闭原则。避免使用多重条件转移语句。提高算法的保密性和安全性。

缺点:客户端必须知道所有的策略类,并且自行决定使用哪一种策略类。产生很多策略类。

例子:

public interface PromotionStrategy {
    void doPromotion();
}
public class FanxianPromotionStrategy implements PromotionStrategy{
    @Override
    public void doPromotion() {
        System.out.println("返现促销,返的金额放到账户余额中。");
    }
}
public class LijianPromotionStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("立减促销,游戏价格直接减去配置的价格");
    }
}
public class ManjianPromotionStrategy implements PromotionStrategy {
    @Override
    public void doPromotion() {
        System.out.println("满减促销,满200减20");
    }
}
public class PromotionActivity {
    private PromotionStrategy promotionStrategy;

    public PromotionActivity(PromotionStrategy promotionStrategy) {
        this.promotionStrategy = promotionStrategy;
    }

    public void executePromotionActivity(){
        this.promotionStrategy.doPromotion();
    }
}
public class Test {
    public static void main(String[] args) {
        PromotionActivity promotionActivity618 = new PromotionActivity(new ManjianPromotionStrategy());
        PromotionActivity promotionActivity1111 = new PromotionActivity(new LijianPromotionStrategy());
        PromotionActivity promotionActivity1212 = new PromotionActivity(new FanxianPromotionStrategy());

        promotionActivity618.executePromotionActivity();
        promotionActivity1111.executePromotionActivity();
        promotionActivity1212.executePromotionActivity();
    }
}

看一下类图

 应用层在不同的促销阶段选择不同的促销策略即可,而且新增一种促销,也只需要实现促销接口即可。

当然,现在这样并不能完全消除ifelse,因为实际上我们在应用层选择哪种促销,还是需要判断的。所以接下来结合工厂模式优化一下:

public class PromotionStrategyFactory {
    private static Map<String , PromotionStrategy> PROMOTION_STRATEGY_MAP = new HashMap<>();
    static {
        PROMOTION_STRATEGY_MAP.put(PromotionKey.LIJIAN , new LijianPromotionStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.MANJIAN , new ManjianPromotionStrategy());
        PROMOTION_STRATEGY_MAP.put(PromotionKey.FANXIAN , new FanxianPromotionStrategy());
    }

    private static final PromotionStrategy NON_PROMOTION = new EmptyPromotionStrategy();
    private PromotionStrategyFactory() {
    }

    public static PromotionStrategy getPromotionStrategy(String key){
        PromotionStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(key);
        return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
    }

    private interface PromotionKey{
        String LIJIAN = "LIJIAN";
        String MANJIAN = "MANJIAN";
        String FANXIAN = "FANXIAN";
    }
}
public class Test {
    public static void main(String[] args) {
        String promotionKey = "LIJIAN";
        PromotionActivity promotionActivity = new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey));
        promotionActivity.executePromotionActivity();
    }
}

看一下现在的类图:

结合工厂模式,可以很简洁的实现。很多时候策略模式都不是单独出现的,都会结合工厂模式、享元模式、单例模式等运用。

用到设计模式的源码:

Comparator就是一个策略接口,很多实现类。看一下Arrays#sort

这里会把Comparator作为参数传递,这里传哪种比较器,就可以用哪种策略了。

再看一个TreeMap


解释器模式

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。简单来说就是为了解释一种语言,而为语言创建的解释器。

类型:行为型

使用场景:某个特定类型问题发生频率足够高的时候(例如有各种各样的日志,格式都不一样,但要的元素都有,这样就可以用一个程序来提取,这个程序就是解释器)。

优点:语法由很多类表示,容易改变及扩展此“语言”。

缺点:语法规则数目太多时,增加系统的复杂度。

例子:

public interface Interpreter {
    int interpret();
}
public class AddInterpreter implements Interpreter {
    private Interpreter firstExpression;
    private Interpreter secondExpression;

    public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() + this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "+";
    }
}
public class MultiInterpreter implements Interpreter {
    private Interpreter firstExpression;
    private Interpreter secondExpression;

    public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        return this.firstExpression.interpret() * this.secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "*";
    }
}
public class NumberInterpreter implements Interpreter {
    private int number;

    public NumberInterpreter(int number) {
        this.number = number;
    }

    public NumberInterpreter(String number) {
        this.number = Integer.valueOf(number);
    }

    @Override
    public int interpret() {
        return this.number;
    }

    @Override
    public String toString() {
        return String.valueOf(this.number);
    }
}
public class OperatorUtil {
    public static boolean isOperator(String symbol){
        return (symbol.equals("+") || symbol.equals("*"));
    }

    public static Interpreter getExpressionObject(Interpreter firstInterpreter , Interpreter secondInterpreter , String symbol){
        if(symbol.equals("+")){
            return new AddInterpreter(firstInterpreter , secondInterpreter);
        }else if(symbol.equals("*")){
            return new MultiInterpreter(firstInterpreter , secondInterpreter);
        }
        return null;
    }
}
public class HaoziExpressionParser {
    private Stack<Interpreter> stack = new Stack<>();

    public int parse(String str){
        String[] strItemArray = str.split(" ");
        for(String symbol : strItemArray){
            if(!OperatorUtil.isOperator(symbol)){
                Interpreter numExpression = new NumberInterpreter(symbol);
                stack.push(numExpression);
                System.out.println("入栈:" + numExpression);
            }else {
                Interpreter fistExpression = stack.pop();
                Interpreter secondExpression = stack.pop();
                System.out.println(String.format("出栈:%s和%s" , fistExpression , secondExpression));
                Interpreter operator = OperatorUtil.getExpressionObject(fistExpression , secondExpression , symbol);
                System.out.println(String.format("应用运算符:%s" , operator));
                int result = operator.interpret();
                NumberInterpreter resultExpression = new NumberInterpreter(result);
                stack.push(resultExpression);
                System.out.println(String.format("阶段结果入栈:%d" , result));
            }
        }
        int result = stack.pop().interpret();
        return result;
    }
}
public class Test {
    public static void main(String[] args) {
        String inputStr = "6 100 11 + *";
        HaoziExpressionParser expressionParser = new HaoziExpressionParser();
        int result = expressionParser.parse(inputStr);
        System.out.println("解释器结果:" + result);
    }
}

结果:

 类图:

应用层传字符串给解释器,解释器来进行解析,并逐个进行判断并计算,最后输出结果。解释器在日常用的很少,但也要了解其原理。 

用到设计模式的源码:

Pattern的正则,还有spring中的ExpressionParser,可以写个例子debug进去看

public class SpringTest {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
        int result = (int) expression.getValue();
        System.out.println(result);
    }
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值