本图片来自深圳一家独角兽公司
神坑面试题之设计模式
当我看到这题目 觉得很有意思 不就是去除if else if 吗? 这不就是典型的策略模式吗?当然单独靠策略模式是无法全部消除if else if的 还需要靠工厂+策略模式 实现消除if
GOF的《设计模式》著作中认为策略模式可以消除一些条件语句,我对此持怀疑态度。正如上面的例子,虽然由于Context在初始化的时候已经指定了策略实现,在计算逻辑中不需要根据条件选择逻辑分支。但是,客户端代码在初始化Context的时候,如何判断应该传入哪个策略实现呢?其实在客户端代码或者别的地方还是缺少不了条件判断。所以这里消除条件语句,只是针对算法逻辑的条件判断。
2. 策略模式优缺点
那么策略模式的优点是什么了?
2.1 优点
- 使用策略模式 可以根据策略接口 定义一系列可供复用的行为和算法;
- 调用方只需要持有context 的引用即可 而无需知道具体策略实现 满足迪米特法则;
- context在策略的方法之外可以做一些通用的切面逻辑
2.2 缺点
- 客户端代码需要知道不同的策略以及如何选择策略。因此可以看到上面的客户端代码有着丑陋的条件判断;
- 由于策略类实现同样的接口,所以参数列表要保持一致,但可能并不是所有的策略都需要全部参数
3. 策略模式与工厂模式结合使用
针对第一个缺点。我们可以通过策略模式与工厂模式结合使用来改进。通过进一步封装,消除客户端代码的条件选择 代码如下
package com.zw.design.pattern.behavioral.mianshi;
public interface IAnimalStrategy {
public void doPromotion() ;
}
package com.zw.design.pattern.behavioral.mianshi;
public class CatStrategy implements IAnimalStrategy {
@Override
public void doPromotion() {
System.out.println("这个是处理猫的类");
}
}
package com.zw.design.pattern.behavioral.mianshi;
public class DogStrategy implements IAnimalStrategy {
@Override
public void doPromotion() {
System.out.println("处理dog行为");
}
}
package com.zw.design.pattern.behavioral.mianshi;
public class EmptyAnimalStrategy implements IAnimalStrategy {
@Override
public void doPromotion() {
}
}
package com.zw.design.pattern.behavioral.mianshi;
public class PigStrategy implements IAnimalStrategy {
@Override
public void doPromotion() {
System.out.println("这是pig的类");
}
}
package com.zw.design.pattern.behavioral.mianshi;
import java.util.HashMap;
import java.util.Map;
public abstract class AnimalStrategyFactory {
private final static Map<String, IAnimalStrategy> PROMOTION_STRATEGY_MAP = new HashMap<String, IAnimalStrategy>();
private interface PromotionKey{
String DOG = "dog";
String PIG = "pig";
String CAT = "cat";
}
public static IAnimalStrategy getPromotionStrategy(String promotionKey){
IAnimalStrategy promotionStrategy = PROMOTION_STRATEGY_MAP.get(promotionKey);
return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
}
private static final IAnimalStrategy NON_PROMOTION = new EmptyAnimalStrategy();
static {
PROMOTION_STRATEGY_MAP.put(PromotionKey.CAT,new CatStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.DOG,new DogStrategy());
PROMOTION_STRATEGY_MAP.put(PromotionKey.PIG,new PigStrategy());
}
}
package com.zw.design.pattern.behavioral.mianshi;
public class AnimalActivity {
private IAnimalStrategy promotionStrategy;
public AnimalActivity(IAnimalStrategy promotionStrategy){
this.promotionStrategy = promotionStrategy;
}
public void executePromotionStrategy(){
promotionStrategy.doPromotion();
}
}
public static void main(String[] args) {
String petType="dog";
AnimalActivity animalActivity=new AnimalActivity(
AnimalStrategyFactory.getPromotionStrategy(petType)
);
animalActivity.executePromotionStrategy();
}
4. 策略模式适用场景
当存在多种逻辑不同,但属于同一类型的行为或者算法时,可以考虑使用策略模式。以此来消除你算法代码中的条件判断。同时让你的代码满足多种设计原则。
很多时候,工厂模式和策略模式都可以为你解决同类问题。但你要想清楚,你想要的是一个对象,还是仅仅想要一个计算结果。如果你需要的是一个对象,并且想用它做很多事情。那么请使用工厂模式。而你仅仅想要一个特定算法的计算结果,那么请使用策略模式。
策略模式属于对象行为模式,而工厂属于创建型模式。策略模式和工厂模式对比如下:
5. 小结
策略模式解决的问题是如何封装可供复用的算法或者行为。策略模式满足了单一职责、开闭、迪米特法则、依赖倒转等原则。我们一定想清楚策略模式的适用场景,否则某些时候你会搞不清到底用工厂模式还是策略模式。最后提醒大家,设计模式很多时候都是混合使用,我们不应该局限于使用某一种设计模式来解决问题。
|