zoukankan      html  css  js  c++  java
  • 23种设计模式之策略设计模式

    策略模式:分别封装行为接口,实现算法组,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。

    策略模式注意点:1)分析项目中变化部分与不变部分;2)多用组合少用继承;用行为类组合,而不是行为的继承更有弹性。

    鸭子游戏项目设计思路

    一般设计是分析鸭子类别,把相同的放在抽象超类中实现,不同的在抽象超类中定义为抽象方法,然后不同的鸭子继承抽象超类,实现抽象方法

    public abstract class Duck {
    
        public Duck() {
    
        }
    
        //鸭子都是一样的叫声
        public void quack() {
            System.out.println("~~gaga~~");
        }
    
        //鸭子都会游泳
        public void swim() {
            System.out.println("~~im swim~~");
        }
    
        //鸭子长相不一样
        public abstract void display();
    
    }
    abstract duck
    public class RedHeadDuck extends Duck {
        public void display() {
            System.out.println("**RedHead**");
        }
    }
    RedHeadDuck extends duck
    public class GreenHeadDuck extends Duck {
        public void display() {
            System.out.println("**GreenHead**");
        }
    }
    GreenHeadDuck

    现在需求要改,鸭子会飞,那就给抽象超类添加一个fly方法,并实现会飞功能

    public abstract class Duck {
    
        public Duck() {
    
        }
    
        //鸭子都是一样的叫声
        public void quack() {
            System.out.println("~~gaga~~");
        }
    
        //鸭子都会游泳
        public void swim() {
            System.out.println("~~im swim~~");
        }
    
        //鸭子长相不一样
        public abstract void display();
    
        //鸭子都会飞
        public void fly() {
            System.out.println("~~fly~~");
        }
    
    }
    超类添加鸭子会飞方法

    然后又改需求,说GreenHeadDuck不能飞了,那就要在GreenHeadDuck中覆盖父类fly方法

    @Override
        public void fly() {
            System.out.println("**im cant fly**");
        }
    greenduck重写父类fly方法

    现在问题来了,就是在父类中实现了一个方法,如果有多个子类跟父类方法不一致,那就要每个不一致的子类都要重写父类方法;如果把超类中fly定义成抽象的,那么相同fly的代码不能重用了,使用和维护上麻烦了

    又有个需求,stone duck既不会飞也不会叫,那么子类中要把fly和quack重写;所以父类挖坑要子类来填,这种设计并不是好的设计

    项目设计方法:分析项目变化部分和不变部分,提取变化部分,抽象成接口+实现

    以鸭子游戏项目为例,假如分析得出鸭子quack和fly是变化的

    根据策略模式,把变化的行为抽象成接口,flybehavior和quackbehavior

    超类中定义接口对象,接口对象调用相应方法,子类只对接口对象做对应的实例化即可

    public interface FlyBehavior {
    
        void fly();
    
    }
    行为接口FlyBehavior
    public interface QuackBehavior {
    
        void quack();
    
    }
    行为接口QuackBehavior
    public class GoodFlyBehavior implements FlyBehavior {
        public void fly() {
            System.out.println("~~good fly~~");
        }
    }
    FlyBehavior实现
    public class GaGaQuackBehavior implements QuackBehavior {
        public void quack() {
            System.out.println("~~ga ga ~~");
        }
    }
    QuackBehavior实现
    public abstract class Duck {
    
        FlyBehavior flyBehavior;
        QuackBehavior quackBehavior;
    
        public Duck() {
    
        }
    
        public void fly() {
            flyBehavior.fly();
        }
    
        public void quack() {
            quackBehavior.quack();
        }
    
        public abstract void display();
    
        public void swim() {
            System.out.println("~~swimming~~");
        }
    
    }
    抽象超类,定义了接口对象
    public class GreenHeadDuck extends Duck {
    
        public GreenHeadDuck(){
            this.flyBehavior=new GoodFlyBehavior();
            this.quackBehavior=new GaGaQuackBehavior();
        }
    
        public void display() {
            System.out.println("**GreenHead**");
        }
    }
    子类根据自己的行为设定行为对象

    同样RedHeadDuck也可以像GreenHeadDuck一样,在自己的类中设定行为对象

    这样有点问题就是一旦子类定义好,就不能动态改变行为了,那么就在超类中定义接口对象的set方法,可以使新实例化后的子类设定新的行为对象

  • 相关阅读:
    数据库表与视图的区别
    maven中snapshot版本和正式版本的区别
    @Retention注解
    java泛型以及通配符
    git 删除了本不应该删除的commit 如何恢复
    ES group分组聚合的坑
    solution for 1006 中国剩余定理
    solution for POJ 1001
    ondraw() 和dispatchdraw()的区别
    android几种定时器机制及区别(转载整理)
  • 原文地址:https://www.cnblogs.com/hujiapeng/p/7898859.html
Copyright © 2011-2022 走看看