美文网首页程序员
java 设计模式(1) - 策略模式

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

作者: 小白201808 | 来源:发表于2018-09-09 12:41 被阅读26次

    设计模式

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

    这样做的好处是:

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

    策略模式的定义:

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

    策略模式的原则:

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

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

    相关文章

      网友评论

        本文标题:java 设计模式(1) - 策略模式

        本文链接:https://www.haomeiwen.com/subject/ihnrgftx.html