Java设计模式(九)
------------策略模式
定义
定义一组策略算法,将每个算法都封装起来,并且使它们之间可以互换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化。
实例
比如一级方程式中的赛车的轮胎,可以使用雨胎,干胎,中性胎;一个Swing 容器可以设定布局管理器,可以是FlowLayout,BorderLayout…;他们都可以动态相互替换,这些都是典型的策略模式。
用法概述
策略模式(Strategy)属于对象行为型设计模式,主要是定义一系列的策略算法,把这些算
法一个个封装成拥有共同接口的单独的类,并且使它们之间可以互换。策略模式使这些算法
在客户端调用它们的时候能够互不影响地变化。这里的算法不要狭义的理解为数据结构中算
法,可以理解为不同的业务处理方法。
这种做法会带来什么样的好处呢?
它将算法的使用和算法本身分离,即将变化的具体算法封装了起来,降低了代码的耦合
度,系统业务策略的更变仅需少量修改。算法被提取出来,这样可以使算法得到重用。
构造
我们延续上面Swing布局管理器的例子,我们这里就模拟一下它的实现,如果感兴趣可以参看JDK的源码。
角色
算法使用环境(Context)角色
通常是一个抽象实体和一组实现子类,在抽象类中定义一个抽象策略的引用,执行这个策略一般以方法的形式定义再在抽象类父中(因为父类并不关心使用的是什么策略),如果有默认策略我们应该在父类中进行指定。
public abstract class AbstractContainer { public String name = ""; // 所有容器都具有的show功能 public abstract void show(); public LayoutStrategy layout;
public LayoutStrategy getLayout() { return layout; }
public void setLayout(LayoutStrategy layout) { this.layout = layout; }
public void doLayout() { if (layout == null) { layout = new BorderLayout(); } layout.layout(); }
}
|
public class MyFrame extends AbstractContainer { @Override public void show() { // TODO Auto-generated method stub layout = new BorderLayout(); this.doLayout(); System.out.println("我是一个自定义窗口"); } }
|
public class MyPanel extends AbstractContainer { @Override public void show() { // TODO Auto-generated method stub //layout=new FlowLayout(); //this.setLayout(layout); this.doLayout(); System.out.println("我是一个自定义面板"); } } |
抽象策略(Strategy)角色
public interface LayoutStrategy { public void layout();
} |
具体策略(Concrete Strategy)角色:
public class BorderLayout implements LayoutStrategy {
@Override public void layout() { // TODO Auto-generated method stub System.out.println("我使用了BorderLayout布局管理器"); }
}
public class FlowLayout implements LayoutStrategy {
@Override public void layout() { // TODO Auto-generated method stub System.out.println("我使用了FlowLayout布局管理器"); } } |
客户端代码:
public class MyTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub AbstractContainer panel=new MyPanel(); panel.show();
AbstractContainer frame =new MyFrame(); frame.show();
//动态改变策略 panel.setLayout(new FlowLayout()); panel.show(); } }
打印结果: 我使用了BorderLayout布局管理器 我是一个自定义面板 我使用了BorderLayout布局管理器 我是一个自定义窗口 我使用了FlowLayout布局管理器 我是一个自定义面板 |
总结
下面是使用策略模式的一些建议:
1) 系统需要能够在几种算法中快速的切换。
2) 系统中有一些类它们仅某些行为策略不同时(通常为拥有同一个父类的子类),可以考虑采用策略模式来进行重构。
3) 系统中存在多重条件选择语句时,可以考虑采用策略模式来重构。
但是要注意一点,策略模式中不可以同时使用多于一个的策略算法。
我们为什么要使用策略模式,用继承不行吗?
继承的缺点:
1.代码在多个子类中重复
2.运行时的行为不容易改变
3.改变会牵一发动全身,造成其他子类不想要的改变。
策略模式优点:
1.方便增加新的处理方式(策略)
2.应付客户改变需求,对于某应用需要采用新的方式,比如改变数据库