美文网首页
设计模式之策略模式

设计模式之策略模式

作者: 零星瓢虫 | 来源:发表于2020-04-15 23:22 被阅读0次

    前言

    本系列设计模式的剖析主要基于Head First的设计模式这本书,同时加上一些自己的理解,从而希望自己能够对设计模式进行更深入的一层理解,同时希望能给看到此篇文章的同学带来一些帮助;

    策略模式

    策略模式,听起来就是一种策略;但是是什么样的策略呢?我们就先简单跟随例子分析起来吧;

    设想这么一种情况,我们有一款游戏,这款游戏里面有很多种鸭子,而不同的鸭子则有不同的外在(比如:红色,绿色),同时发出的叫声可能也不同,而同时又可能有的会游泳,有的会飞;

    那么我们首先会想到如何去实现这个鸭子的结构?
    1 定义一个Duck类的父类,定义一些抽象方法;
    2 子类集成Duck ,去实现相关的抽象方法;

    public abstract class Duck {
        abstract void display();
        
        abstract void swim ();
        
        abstract void quak();
    
    }
    
    
    
    public class RedDuck extends Duck{
        
        void display() {
            // TODO Auto-generated method stub
            System.out.print("红鸭子");
    
        }
    
        void swim() {
            // TODO Auto-generated method stub
            System.out.print("鸭子去游泳");
    
        }
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    
    
    public class GreenDuck extends Duck {
    
        void display() {
            // TODO Auto-generated method stub
            System.out.print("绿鸭子");
    
        }
    
        void swim() {
            // TODO Auto-generated method stub
            System.out.print("鸭子去游泳");
    
        }
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    
    public class HanDuck extends Duck{
        void display() {
            // TODO Auto-generated method stub
            System.out.print("绿鸭子");
    
        }
    
        void swim() {
            // TODO Auto-generated method stub
            System.out.print("旱鸭子不会去游泳");
    
        }
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    

    上面可以看到定义了Duck父类,并且GreenDuck,RedDuck,HanDuck分别对父类的抽象方法进行了具体化;到这里看到是没有任何问题的。

    但是现在需求要变了,会游泳的鸭子逻辑有点变化了,我先要判断这只是是否已经到达1岁了,到达了才让它去有泳;其实我们现实开发中也会有这样可能存在变化的逻辑;我们要去如何处理呢?

    public class GreenDuck extends Duck {
    
        void display() {
            // TODO Auto-generated method stub
            System.out.print("绿鸭子");
    
        }
    
        void swim() {
            if(age > 1){
            // TODO Auto-generated method stub
            System.out.print("鸭子去游泳");
            }
    
        }
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    
    public class RedDuck extends Duck{
        
        void display() {
            // TODO Auto-generated method stub
            System.out.print("红鸭子");
    
        }
    
          void swim() {
            if(age > 1){
            // TODO Auto-generated method stub
            System.out.print("鸭子去游泳");
            }
    
        }
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    

    类似于上面,正常情况我们想的是把对应的实现方法修改即可。在这里我们只有一个子类,但是如果在现实中我们有许多子类,那样岂不是意见很麻烦的事情,于是我们把对应的容易改变的行为,做成一个接口,这样我们将动作委托给接口,改动的时候就会变得简单了许多;

    我们先对动作定义接口:

    public  interface SwimInterface {
        void swim();
    
    }
    

    然后具体对不同鸭子游泳方式的实现:

    public class CanSwim implements SwimInterface {
        @Override
        public void swim() {
            // TODO Auto-generated method stub
            if(duck.age > 1){
                System.out.print("去游泳");
            }   
        }
    }
    
    public class NoSwim implements SwimInterface {
    
        public void swim() {
            // TODO Auto-generated method stub
            System.out.print("不会游泳啊啊");
        }
    }
    
    

    这里我们针对不同的游泳方式实现了游泳动作的接口,NoSwim 和CanSwim 分别代表不会游泳和会游泳的类;接下来我们就应该把鸭子的游泳方式委托给接口类来做;

    public abstract class Duck {
        
        SwimInterface swimInterface;
        
        public Duck(){
            
        }
        
        
        abstract void display();
        
         void swim (){
             if(swimInterface != null){
                 swimInterface.swim();
             }
         }
        
        abstract void quak();
    
    }
    
    public class GreenDuck extends Duck {
    
        void display() {
            // TODO Auto-generated method stub
            System.out.print("绿鸭子");
    
        }
        public GreenDuck(){
            swimInterface = new NoSwim();
        }
    
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    
    
    public class HanDuck extends Duck{
        
        public HanDuck(){
            swimInterface = new CanSwim();
        }
        
        void display() {
            // TODO Auto-generated method stub
            System.out.print("绿鸭子");
    
        }
    
    
        void quak() {
            // TODO Auto-generated method stub
            System.out.print("呱呱交");
    
        }
    
    }
    

    这样我们就把游泳这个动作委托出去了,从而当某个游泳方式发生改变的时候,我们只需要修改实现类中的方法即可,比如我现在需要大于2岁才可以去游泳;

    public class CanSwim implements SwimInterface {
        @Override
        public void swim() {
            // TODO Auto-generated method stub
            if(duck.age > 2){
                System.out.print("去游泳");
            }   
        }
    }
    

    只需要改变CanSwim 类中的实现方式即可,任何调用这个方法的同时会被改变;

    public class Main {
        public static void main(String [] args){
            Duck duck = new HanDuck();
            duck.swim();
        }
    }
    

    打印日志;

    去游泳
    
    public abstract class Duck {
        
        SwimInterface swimInterface;
        
        public Duck(){
            
        }
        
        public void setSwimInterface(SwimInterface swimInterface){
            this.swimInterface = swimInterface;
        }
        
        
        abstract void display();
        
         void swim (){
             if(swimInterface != null){
                 swimInterface.swim();
             }
         }
        
        abstract void quak();
    
    }
    
    

    同时我们可以提供ser方法来进行接口的动态设置;

    这样,策略模式就这样诞生;其中心思想就是对于可能会经常变化的东西,我们尽量使用接口来进行编程;满足我们“多用组合,少用继承”的设计原则,可以在运行时候动态地去改变行为;

    最后我们对应来看一下策略模式的UML图形:

    窝藏大莴笋_001.png

    相关文章

      网友评论

          本文标题:设计模式之策略模式

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