目录
迭代器模式
提供一种方法,顺序访问一个集合对象的各个元素,又不暴露该对象的内部表示。简单来说就是遍历。
类型:行为型
使用场景:访问一个集合对象的内容而无需暴露它的内部表示。为遍历不同的集合结构提供一个统一的接口。
优点:分离了集合对象的遍历行为。
缺点:类的个数成对增加。
例子:
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);
}
}