java 设计模式(1) - 策略模式

设计模式

含义:是人们在面对同类型软件工程设计问题总结出来的一些有用的经验!!!
    模式不是代码,而是某类问题的通用设计解决方案。嗯,你可以理解是解决一种类型问题的套路。
    
目的:是软件工程在维护性,扩展性,变化性,复杂度方面成为O(n).

面向对象(OO)是原则 ,设计模式是解决问题的方法。 

一.策略模式

1.从项目“记录自己的朋友行为”开始。

(1)我们先从面向对象的角度设计这个项目,朋友父类
//首先我们把自己的朋友共同有的性质,封装成一个父类
package com.java.stimulateFriend.oo;

public abstract class Friend {
    //构造方法
    public Friend() {}
    //会讲普通话
    public void speaking() {
        
        System.out.println("我会讲普通话!!");
    }
    //会吃
    public void  eatting() {
        
        System.out.println("我是吃货!!!");
    }
    //主修科目 让子类具体实现 因为主修科目不同
    public abstract void subject();
    
}

然后我有俩个朋友 分别继承friend

//一个friend叫keen
package com.java.stimulateFriend.oo;

public class Keen extends Friend {

    @Override
    public void subject() {
        System.out.println("我主修计算机");
        
    }

}
//另外一个friend叫spohie.
package com.java.stimulateFriend.oo;

public class Sophie  extends Friend{

    @Override
    public void subject() {
        System.out.println("我主修英语");
        
    }

}

测试类

package com.java.stimulate.test;

import com.java.stimulateFriend.oo.Keen;
import com.java.stimulateFriend.oo.Sophie;

public class test {

    public static void main(String[] args) {
        //创建对象
        Sophie  sophie = new Sophie();
        Keen keen = new Keen();
     
        //调用方法
        sophie.subject();
        sophie.eatting();
        sophie.speaking();
    
        keen.subject();
        keen.eatting();
        keen.speaking();

    }

}
//output:
我是sophie,主修英语
是个吃货!!!
会讲普通话!!
我是keen,我主修计算机
是个吃货!!!
会讲普通话!!

(1)新的需求:然而随着朋友的长大,她们又学会了一项新技能,会跳舞。(此时你会觉得继承多好呀,增加代码的复用,嗯,确实有时候挺好的!)

用面向对象的思维,我们会直接在Friend超类中增加一项跳舞的技能

package com.java.stimulateFriend.oo;

public abstract class Friend {
    ...
    ...
   public void dancing() 
   {
        System.out.println("会跳舞了!!!");
    }
    
}

(2)新的需求:然而在我的成长过程中,我又交一个新的盘友了,他会唱歌哦,很好听!!!

那么问题来了,我在增加这个朋友的时候,如果我把唱歌这项功能放在Friend超类里,是不是所有的朋友都特别会唱歌了???可是现实中我的其他朋友是音痴呀,这是不是就不科学了呢!!!!然后你想,在不会唱歌的朋友那里进行方法的覆盖,可是盆友有很多的时候,是不是就增加了很多代码量了呀!!!不划算,好累。
此时我们又会想到让这个朋友自己实现这个方法就好了,不加超类,不就完了么!!!可是我以后还会通过他认识更多会唱歌的盆友呀,又在会唱歌的朋友那一个一个的实现吗???是不是很麻烦???而且假如这个朋友也不会跳舞耶!!!咋整???

2.在这里,我们可以发现:

 继承问题:在对类的局部改动,尤其是超类(父类()的局部改动,会影响其他子类,影响会有溢出效益。
 
 换句话说就是:超类挖的一个坑,每个子类都要来填,而且这个坑,有的子类不需要,此时复杂度大大的增加了. O(N^2)

3.此时救星来了(策略模式!!!)

 需要新的设计模式,应对项目的扩展性,降低复杂度。下面就开始学习第一个设计模式 ———— 策略模式。
(1)分析项目中变化与不变化的部份,提取变化的部分,抽象成接口+实现;

接着上面,我们想哪些行为会是以后变化的,比如:唱歌,跳舞....

此时我们抽取出来 ,用接口实现

1.创建一个唱歌的接口

package com.java.friendsingbehavior;

public interface SingBehavior {
   void singing();

}

2.实现唱歌的行为

//会唱歌GoodSing
package com.java.friendsingbehavior;

public class GoodSing implements SingBehavior {

   @Override
   public void singing() {
       System.out.println("我唱歌非常棒!!!");
       
   }

}
//不会唱歌
package com.java.friendsingbehavior;

public class BadSing implements  SingBehavior {

   @Override
   public void singing() {
       System.out.println("我是音痴!");
       
   }

}

3.创建跳舞的接口

package com.java.friend.dancingbehavior;

public interface DancingBehavior {
     void dancing();
}

4.实现跳舞的行为

//BadDancing
package com.java.friend.dancingbehavior;

public class BadDancing implements DancingBehavior{

    @Override
    public void dancing() {
        
        System.out.println("my dancing is so bad!!!");
    }

}
//Gooddancing
package com.java.friend.dancingbehavior;

public class Gooddancing implements DancingBehavior {

   @Override
   public void dancing() {
       System.out.println("my  dancing is good !!");
       
   }

}

5.朋友类(父类)

package com.java.stimulate.Friend;

import com.java.friend.dancingbehavior.DancingBehavior;
import com.java.friendsingbehavior.SingBehavior;

public abstract class Friend {
    SingBehavior singbehavor;

    DancingBehavior dancingbehavior;

    // 构造方法
    public Friend() {
    }

    // 会讲普通话
    public void speaking() {

        System.out.println("会讲普通话!!");
    }

    // 会吃
    public void eatting() {

        System.out.println("是个吃货!!!");
    }

    // 主修科目
    public abstract void subject();

    // 在这里我们就不用实现唱歌的方法了,直接用接口方法
    public void singing() {
        singbehavor.singing();
    }

    // 跳舞同理
    public void dancing() {
        dancingbehavior.dancing();
    }
 //设置setter属性以便以后动态地改变这些行为
    public void setSingbehavor(SingBehavior singbehavor) {
        this.singbehavor = singbehavor;
    }

    public void setDancingbehavior(DancingBehavior dancingbehavior) {
        this.dancingbehavior = dancingbehavior;
    }

}

6.(1)我的朋友keen

package com.java.stimulate.Friend;

import com.java.friend.dancingbehavior.*;
import com.java.friendsingbehavior.*;

public class Keen extends Friend {
     public Keen() {
         singbehavor =  new BadSing();
         dancingbehavior = new Gooddancing();
     }
    @Override
    public void subject() {
        System.out.println("我是keen,学计算机的!!");
    }

}

6.(2)我的朋友sophie

package com.java.stimulate.Friend;

import com.java.friend.dancingbehavior.*;
import com.java.friendsingbehavior.*;
public class Sophie extends Friend{
     public Sophie() {
         singbehavor =  new GoodSing();
         dancingbehavior = new BadDancing();
     }
    @Override
    public void subject() {
        System.out.println("我是Sphoie,我学英语!!");
        
    }

}

7.测试类:

package com.java.stimulate.test;

import com.java.friend.dancingbehavior.*;
import com.java.stimulate.Friend.*;

public class test_01 {
    public static void main(String[] args) {
        //创建对象
        Friend  sophie = new Sophie();
        Friend   keen = new Keen();
        sophie.subject();
        sophie.eatting();
        sophie.speaking();
        sophie.dancing();
        //在这里我们可以动态的改变跳舞唱歌的行为,
        //因为在之前我们设计setter属性
        //System.out.println("change letter!");
        //sophie.setDancingbehavior(new Gooddancing());
        sophie.dancing();
        sophie.singing();
        
        keen.subject();
        keen.eatting();
        keen.speaking();
        keen.dancing();
        keen.singing();
        
    }

}

output:

我是Sphoie,我学英语!!
是个吃货!!!
会讲普通话!!
my dancing is so bad!!!
//change letter!
//my  dancing is good !!
我唱歌非常棒!!!
我是keen,学计算机的!!
是个吃货!!!
会讲普通话!!
my  dancing is good !!
我是音痴!
     

说明:此时就算keen没有唱歌的能力,我们在keen类里(子类)不创建singbehavor = new GoodSing();不实现也不会报错的,sophie同理啦~(是不是没有坑了)

这样做的好处是:

 新增行为简单,行为类更好得复用,组合更方便,竟可以有继承带来代码复用的好处,又没有挖坑。

策略模式的定义:

 分别封装行为接口,实现算法族,父类里放行为接口对象,在子类的构造方法里具体实现设定行为对象。

策略模式的原则:

 分离变化部分,封装接口,基于接口编程各种行为。此模式让算法的变化独立与算法的使用者。(好官方呀!!!)    

这是本人学习过程中自己举例理解策略模式的例子,可能存在很多的局限性,若有不恰当的地方,希望小伙伴指出讨论,谢谢啦~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 设计模式是人们在面对同类型软件工程设计问题所总结出的一些有用的经验。模式不是代码,而是某类问题的通用设计解决方案。...
    磊_lei阅读 3,408评论 2 3
  • 设计模式概述 在学习面向对象七大设计原则时需要注意以下几点:a) 高内聚、低耦合和单一职能的“冲突”实际上,这两者...
    彦帧阅读 9,170评论 0 14
  • 参考资料:菜鸟教程之设计模式 设计模式概述 设计模式(Design pattern)代表了最佳的实践,通常被有经验...
    Steven1997阅读 4,930评论 1 12
  • 我们同事直接会吐槽自己的办公室是小作坊,一个只有五十多坪的小作坊。 但这样的小作坊里有一群90的妹子,做些跨国的新...
    元气满满的慧慧酱阅读 3,902评论 0 0
  • 酷暑真格难耐!尤其是今年的暑天。今早六点钟,骑自行车赶早市时,市场上已人声鼎沸,非常热闹了。骑车驮着买到的瓜果蔬菜...
    怡若泰然阅读 1,882评论 0 0

友情链接更多精彩内容