Strategy设计模式

来源:互联网 发布:手机优化软件排名第一 编辑:程序博客网 时间:2024/04/19 18:40

Strategy策略模式是属于设计模式中对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.我们达到了在运行期间,可以自由切换算法的目的。实际整个Strategy的核心部分就是抽象类(或者接口)的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速.一直有点糊涂的地方就是factory&strategy,实际上StrategyFactory有一定的类似,Strategy相对简单容易理解,并且可以在运行时刻自由切换Factory重点是用来创建对象

 

设计模式就是把简单的东西复杂化,但是有理有据,看你将来在那个方向做扩展,那么就会在那个方向上复杂化,等等,农场生小母牛,那类与类之间的关系太简单了,感受不到系统之间的精妙的结构的乐趣.设计模式可以让你感受到这才是面向对象的乐趣精华所在!

 

设计模式笔记上的例子比较好,这里拿过来为以后的理解做铺垫。

 

TextStrategy是个抽象类,内含抽象方法:replacelinuxstrategy,windowsstrategy继承这个抽象类,同时各自实现方法replace,textCharChange调用textStrategy类中的replace方法进行使用,

 

TextStrategy抽象类的结构:

public abstract classTextStrategy {

    protected String text;

    public TextStrategy(String text) {

        this.text = text;

    }

    public abstract String replace();

} 

Linux的实现策略:

public classLinuxStrategy extends TextStrategy {

   publicLinuxStrategy(String text) {//构造方法

        super(text);

    }

   public String replace() {//实现的具体方法,这才是核心

        preOperation();

        System.out.println(text =text.replaceAll("@r@n", "@n"));

        postOperation();

        return text;

    } } 

Windows实现策略:

public classWindowsStrategy extends TextStrategy {

    public WindowsStrategy(String text) {

        super(text);

    }

    public String replace() {

        startOperation();

        System.out.println(text =text.replaceAll("@n", "@r@n"));

        endOperation();

        return text;

    }}

整合在一起使用的类:

public classTextCharChange {

   public static voidreplace(TextStrategy strategy) {//传策略的参数,直接调用,这儿很巧妙!!

        strategy.replace();

   } }

测试类:

public class Main {

    public static void main(String[] args) {

        String linuxText =  "This is a test text!!@n Oh! LineReturn!!@n";

        String windowsText = "This is atest text!!@r@n Oh! Line Return@r@n";

       TextCharChange.replace( new WindowsStrategy(linuxText));//直接调用就行!

        System.out.println();

  TextCharChange.replace( newLinuxStrategy(windowsText));

    }}


 

strategy模式的结构图,三个具体策略的实现类,一个抽象类或接口,另外一个整合使用的类,直接调用整合后的类即可~~

 以上是strategy模式笔记比较简单的用法,但是看sp学习的话,马老师给出了一个很复杂的例子,有点迷糊,没具体操作。。下次再写吧,或者就不写了,其实也很简单,他的流程是这样的:

首先用一般的sort方法,想着sort的复用而让需要排序的类:cat,dag实现comparable接口,实现comparTo方法,通过这个方法对这个类的两个对象比较大小,为了实现对同一类的不同属性的大小的比较,而对每个类生成多个比较策略类:CatHeightComparator,CatWeightComparator,这两个比较策略使用时可以随时调用。


分析了下sp中讲到的例子,对cat对象比较大小,总共有两个接口:comparable,comparator,其中comparable中方法为:compareTo(0)comparator方法:compare(0,0),cat实现了comparable接口,实现compareTo()方法时,使用了compartor.compare()方法,及动态调用需要用到的比较策略:heighe,or weighte比较策略。HeightCompareWeightCompare都实现了compartor接口,实现了compare方法。dataSorter类对数组中的所有对象进行sort操作。test是测试类。




具体代码如下:

两个接口的就省了,写cat的实现:

public class Catimplements java.lang.Comparable<Cat> {

privateint height;

privateint weight;

//privateComparator comparator = new CatHeightComparator();

privatejava.util.Comparator<Cat> comparator = new CatHeightComparator();//此处已经赋值了,不如第一个例子中的给的动态性强

public Cat(Comparator comparator, int height, int weight) {//这样就可以了。。
super();
this.comparator = comparator;
this.height = height;
this.weight = weight;
}

@Override

publicString toString() {//便于对象的输出,若没有的话,只会输出对象在内存中的引用,是一串引用代码;

returnheight + "|" + weight;}

@Override

publicint compareTo(Cat o) {//调用comparator的compare方法,这里如上一个例子中的textChartChange中的replace方法一样,但是此处调用不很灵活

return comparator.compare(this, o);//可以再为对像初始化时,传一个比较器接口,然后进行比较~

}}

HeightCompare实现:weightCompare省掉。

public classCatHeightComparator implements java.util.Comparator<Cat> {

@Override

publicint compare(Cat o1, Cat o2) {//真正比较策略的实现,将方法封装成类,方便动态调用而不用该代码;

Catc1 = (Cat)o1;

Catc2 = (Cat)o2;

if(c1.getHeight()> c2.getHeight()) return 1;

elseif(c1.getHeight() < c2.getHeight()) return -1;

return0;

}}

DataSort实现:

public classDataSorter {

public static voidsort(Object[] a) {

for(inti=a.length; i>0; i--) {

for(intj=0; j<i-1; j++) {

Comparableo1 = (Comparable)a[j];

Comparableo2 = (Comparable)a[j+1];

if(o1.compareTo(o2)== 1) {//真正用的地方!实际上,compareTo方法调用了cat内的comparetor对象的compare方法;

swap(a,j , j+1);//工具方法

}}}}

privatestatic void swap(Object[] a, int x, int y) {//注意参数的传递,此处要有数组a ,不然起不到换位置的作用!

Objecttemp = a[x];

a[x]= a[y];

a[y]= temp;}

}

Test类实现:

public class Test {

publicstatic void main(String[] args) {

Cat[] c = { new Cat(new CatWeightComparator(), 1, 2),//动态传比较的属性值过来,这样就可以了!

new Cat(new CatWeightComparator(), 27, 1),
new Cat(new CatWeightComparator(), 22, 3) };
DataSorter.sort(a);//直接调用dataSorter的sort方法,sort中调用comparable对象的compareTo方法,compareTo方法实际上调用的是comparable对象中comparetor对象的compare()方法,所以真正实现在comparetor实现类的compare方法中!

DataSorter.p(a);//打印出结果

}}

这个比上面那个例子复杂在:cat本身也是一个实现了comparable接口的类,这样就跟compartor有点混淆了!其实真正的含义有两点:

1.实现comparable对象的比较,并且做到datasort sortor方法的可重用性;

2.对同一comparable对象的不同比较方法的实现,并且用动态调用的方式使用;(当然这里面没有例子以做的好,因为compartor对象是写死在cat类里的,最好的是在使用时,通过参数传过来!)

3.与State一样,例子中完美的面向对象的思维,用TextCharChange完美的把接口及其实现封装起来,用的时候直接提供TextCharChange就行!赞一个!!而且方法名称都一样:replace.不会像后面那个例子那样容易混淆!当然后面的例子也有他的原因,因为他是要封装整个DataSorter类及其sorter方法达到最好的复用性,所以首先要对外提供一个comparable的接口的参数传递,使得实现这个接口的所有的类都能调用这个方法进行sort,然后就涉及到,实现类可以调用方法进行比较了,但是真正的比较过程与简单的数据类型又不相同,因为是类的比较,有会考虑比较那个属性?为了提供更好的多态或者扩展性,就要对外提供一个很比较方法的策略参数的传值:CatWeightCompartor()类实现了对重量的比较的策略,所以传递这个类的对象可以实现这种比较策略,同理,相同的策略是要实现于统一的接口的,才能保证被接受这个参数的方法使用!所以,catweightcompartor实现了compartor接口!

所以,仔细分析才知道,实际上是有两层策略(sort,compareTo),每一层的使用都会用到接口.sort为了实现对comparable的对象的比较,comparTo为了实现对同一对象的多种不同的比较方式!


原创粉丝点击