设计模式(十一)—— 策略模式

一、定义:

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

二、特点:

  • 环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
  • 抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
  • 具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。

三、情景:

设计一个鸭子,会有很多种不同的鸭子,比如说白头鸭、黑头鸭、橡皮鸭、木头鸭等等,这些鸭,有的会叫,有的不会,有的会飞,有的不会,但每一个鸭都会游泳。让你来设计要怎么设计。

设计一:最差的方法

有多少只鸭就建多少个类,这样重复性的工作量太大,代码会十分的难看

设计二:稍微好一点的方法

对这些鸭抽象一下,比如说所有的鸭都会游泳,就创建一个抽象类,类中实现了游泳的方法。
其他的叫、飞等行为写在每个鸭的实现类中。

设计三:再优化一点的方法

把叫和飞这两种行为再抽象出来,形成两个接口,每个鸭都要继承抽象鸭,并且实现飞和叫这两种接口。
但这样有一个问题,有些鸭其实都可以叫的,而且叫的方式都一毛一样。如果每个都这么写得话,也会带来挺大的工作量,所以还需要再进一步优化

设计四:最终优化

将叫和飞两种行为接口,作为实例放到抽象鸭的类中,使用面向接口的方式来实现

抽象鸭类

public abstract class Duck {
    
    FlyBehavior flyBehavior;
    JiaoBehavior jiaoBehavior;

    .........
}

鸭会飞行为实现类

public class CanFly implements FlyBehavior
{


}

某具体的种类的鸭

public class ZhouHeiDuck extends Duck{
    public ZhouHeiDuck(){
        flyBehavior = new CanFly();
    }
}

总结

上面的例子很具有代表性。也反映了设计的两个原则:

1、需要改变的东西和不需要改变的东西要分离开,确切的说,应该要将会改变的东西独立出来

2、针对于接口编程而不是针对于实现编程

应用场景

使用注解实现对支付方式的策略封装

定义注解


@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface PayType {

    String desc();

    PayTypeEnum type();

}

定义枚举类

public enum  PayTypeEnum {

    ALIPAY(1),
    WECHAT(2);

    PayTypeEnum(int type) {
        this.type = type;
    }

    private int type;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

}

定义接口与实现类

public interface IPayService {
    String pay(BigDecimal amount);
}
@Service
@PayType(desc = "微信支付", type = PayTypeEnum.WECHAT)
public class WechatPayService implements IPayService {

    @Override
    public String pay(BigDecimal amount) {
        System.out.println("微信到帐{}元!" + amount);
        return "success";
    }

}
@Service
@PayType(desc = "支付宝支付",type = PayTypeEnum.ALIPAY)
public class AlipayPayService implements IPayService{

    @Override
    public String pay(BigDecimal amount) {
        System.out.println("支付宝到帐{}元!"+amount);
        return "success";
    }

}

网关类

@Service
public class PayGateWayService {

    @Autowired
    private List<IPayService> payServiceList;

    public IPayService route(int type) throws Exception {
        for (IPayService payService : payServiceList) {
            PayType payTypeAnnotation = payService.getClass().getAnnotation(PayType.class);
            if (payTypeAnnotation.type().getType() == type) {
                System.out.println("路由到具体的支付业务类为:" + payService.getClass().getSimpleName());
                return payService;
            }
        }
        throw new Exception("没有找到具体支付业务类");
    }

}

测试类

    @Test
    public void test() {
        int type = PayTypeEnum.WECHAT.getType();//支付宝支付
        BigDecimal amount = BigDecimal.valueOf(100);//支付金额 100 元
        IPayService payService = null;//支付网关类
        try {
            payService = payGateWayService.route(type);
            payService.pay(amount);//开始支付
        } catch (Exception e) {
            System.out.println("支付异常");
        }
    }
posted @ 2016-11-22 22:52  清泉白石  阅读(280)  评论(0编辑  收藏  举报