zoukankan      html  css  js  c++  java
  • 每天一种设计模式(一)-- 策略模式

    目的:将对象和行为解耦。由继承得来的行为,灵活性不够,行为是写死在类中的。如果需要修改,
    只能修改原来的类。如果修改超类,则所有子类都受影响。如果修改子类,那么子类中会出现大量
    重复代码。比如有十个子类,它们的行为与超类行为不同,则要修改十个子类。问题是,这十个子
    类的行为是一致的,却无法将行为重用。将行为抽离出来,则可以达到共用的目的。

    1. 只需要在对象中包含一个行为对象,调用行为对象的方法来完成对应行为即可。

    2. 行为对象要实现特定行为的接口。

    比如一个Person对象,有吃饭,睡觉的行为。当然,你可以说人的吃和睡,能有什么差别。是的,大
    部分人都是一样的。但是,有的人,就细嚼慢咽,有的人,则狼吞虎咽,对于一种行为来说,这确实是
    有差别的。有的人睡觉很安静,有的人睡觉打呼噜,还的的人睡觉睁着眼睛,这也是差别。具体什么样
    的差别算差别,还是业务逻辑说了算。

    这时,最基本也是最直接的方式,就是在Person类中实现默认的,普遍的吃饭和睡觉方法。然后子类中
    那些特别的人,去覆盖对应的方法。这时候,问题来了,有的人睡觉很安静,吃饭狼吞虎咽;有的人睡觉
    很安静,吃饭细嚼慢咽;有的人睡觉打呼噜,吃饭狼吞虎咽。。。。对于这些拥有不同行为的人,要
    创建它们的实例,就得根据行为不同,组合出各种不同的类,类爆炸来了。

    public class Person {
    
    	public void sleep() {
    		System.out.println("普通人睡觉");
    	}
    	
    	public void eat() {
    		System.out.println("普通人吃饭");
    	}
    }
    class Snorer extends Person{
    	public void sleep() {
    		System.out.println("呼噜。。。呼噜。。。");
    	}
    }
    
    class Huger extends Person{
    	public void eat() {
    		System.out.println("狼吞虎咽");
    	}
    }
    
    // 更多形形色色的组合
    

    策略模式很好的解决了这个问题。
    将睡觉,吃饭这些行为分离出去,不在是Person类的方法。而是单独的行为对象。行为对象只需要实现
    行为接口。睡觉这个行为对象,实现了睡觉行为接口,假设为: interface Sleep 这个接口中,只有
    一个方法, void sleep(); 很明显,行为对象实现此接口,只需要实现sleep方法即可。吃饭行为对象
    也是一样。

    现在行为对象有了,怎么和Person对象联系起来呢?

    需要在Person类内部创建一个实例变量: Sleep sleepBehavior;
    将以前硬编码在Person类内部的 sleep,eat方法做下修改。

    interface Sleep{
      void sleep();
    }
    interface Eat{
      void eat();
    }
    public class SnorerSleep implements Sleep{
      System.out.println("呼噜。。。呼噜。。。");
    }
    public class HugerEat implements Eat{
      System.out.println("狼吞虎咽");
    }
    public abstract class Person{
    	Sleep sleepBehavior;
    	Eat eatBehavior;
    	public void sleep(){
     		sleepBehavior.sleep();
    	}
    	public void eat(){
    		eatBehavior.eat();
    	}
    }
    
    public class Snorer extends Person{
    
      public Snorer(){
        this.sleepBehavior = new SnorerSleep();
      }
    }
    
    new Snorer().sleep(); // 呼噜。。。呼噜。。。
    

    如果需要在运行时,动态的改变Person对象的行为,可以添加 sleepBehavior 和 eatBehavior 的setter
    ,调用之后,实例的行为就会发生变化。

    这样,行为得到了复用,并且和对象解耦了。是不是更容易维护了?

    缺点:

    1. 会产生很多策略类,但是相对原来的模式,要好很多。
    2. 需要了解所有的策略,才能作出正确的选择。但是,代码是咱们写的,这不是什么问题。有文档,更简单。
  • 相关阅读:
    Java学习笔记之——封装
    Java学习笔记之——String和Arrays常用方法
    Flask+uwsgi+virtualenv环境配置
    shell常用函数封装-main.sh
    APK模式下,epg版本升级,需要做同步
    cboss升级顺序
    Mariadb使用xtrabackup工具备份数据脚本
    Seaweedfs-启动脚本
    运营商-工作内容调整记录
    MSC服务器-主从检测脚本-check_server_state.sh
  • 原文地址:https://www.cnblogs.com/zhangfengyang/p/8232453.html
Copyright © 2011-2022 走看看