zoukankan      html  css  js  c++  java
  • 策略模式

          策略模式采用组合的形式,把一个算法任务委托给被组合的接口,根据运行时传入对象的不同,算法可以做到相互替换,同时这些变化可以独立于具体的使用者。

          例如,一般车上都会有喇叭,不同的车喇叭的声音不一样,将车抽象成一个接口如下:

    1 public interface Vehicle{
    2     void whistle();  //鸣笛
    3 }

          我们都知道,自行车按铃是“铃铃铃”的声音,而小汽车则是“嘀嘀”声,它们都实现了Vehicle接口:

     1 public class Bike implements Vehicle{
     2     public void whistle(){
     3         System.out.println("铃铃铃。。。");
     4     }
     5 }
     6 
     7 public class  implements Vehicle{
     8     public void whistle(){
     9         System.out.println("嘀嘀。。。");
    10     }
    11 }

          现在,自行车和小汽车都能够正常的鸣笛了。然而,这种类结构有一个问题,假设小汽车的喇叭坏了,这个时候调用它的 whistle 方法没有发出任何声音,我们需要换一个喇叭。然而由于 whistle 方法是与具体的车(Car)绑定在一起了,要换喇叭,只能连车一起换了,这显然不划算,所以需要将喇叭与车进行重新设计,让喇叭只是作为车里面的一个可以随时更换的配件。让喇叭作为一个接口独立出来,并且在车里放置一个喇叭对象,需要鸣笛的时候,将鸣笛的任务交给喇叭就可以了。

          首先,抽象出来一个喇叭接口:

    1 public interface Horn{
    2     void ring();    //喇叭会响
    3 }

          每个车也都需要一个喇叭:

    1 public interface Vehicle{
    2     Horn horn;
    3     void whistle();  //鸣笛
    4 }

          然后,针对自行车和小汽车,分别设计各自的车铃:

     1 // 自行车铃
     2 public class Bicyclebell implements Horn{
     3     public void ring(){
     4         System.out.println("铃铃铃。。。");
     5     }
     6 }
     7 
     8 // 汽车车铃
     9 public class CarbellDiDi implements Horn{
    10     public void ring(){
    11         System.out.println("嘀嘀。。。");
    12     }
    13 }
    14 
    15 // 汽车车铃
    16 public class CarbellBaBa implements Horn{
    17     public void ring(){
    18         System.out.println("叭叭。。。");
    19     }
    20 }

          接着在自行车和汽车上都放置一个车铃:

     1  public class Bike implements Vehicle{
     2       // 自行车需要自行车车铃
     3      public Bike(){
     4          this.horn = new Bicyclebell();
     5      }
     6  
     7       public void whistle(){
     8          horn.ring();
     9       }
    10  
    11      public void setHorn(Horn horn){
    12          this.horn = horn;
    13      }
    14   }
    15   
    16   public class Car implements Vehicle{
    17      // 汽车需要汽车铃
    18      public Car(){
    19          this.horn = new CarBellDiDi();
    20      }
    21  
    22       public void whistle(){
    23           horn.ring();
    24      }
    25  
    26      public void setHorn(Horn horn){
    27          this.horn = horn;
    28      }
    29   }

          接下来写一段程序测试一下我们的代码,看看是否能够达到预期:

     1 public static void main(String[] args){
     2     Vehicle bike = new Bike();
     3     bike.whistle();   // 铃铃铃。。。
     4     
     5     Vehicle car = new Car();
     6     car.whistle();  // 嘀嘀。。。
     7     
     8     //给汽车换个喇叭
     9     car.setHorn(new CarbellBaBa());
    10     car.whistle();  //叭叭。。。
    11 }

          可以看到,自行车和汽车成功的鸣笛了,并且我们成功地给汽车换了个喇叭。当然,可以看到子类中的whistle方法代码逻辑都一样,有些重复,我们完全可以将Vehicle变成一个抽象类,然后在其whistle方法里调用horn的ring方法,这样就可以减少许多冗余的代码,不过这不是本文的重点,这种实现方式暂且略过。

          现在重新审视一下这个设计,不同的车铃对应着不同的策略,而车则是策略的使用者,通过组合的方式,实现了策略与使用者之间的解耦,并且通过setter方法可以动态的更改策略,这种做法便是运用了策略模式。

    参考:<<Head First设计模式>>

  • 相关阅读:
    NS3系列—4———NS3中文教程5:Tweaking NS3
    NS3系列—3———NS3中文:4 概念描述
    NS3系列—2———NS3笔录
    NS3系列—1———NS3中文教程:3下载及编译软件
    How to speed my too-slow ssh login?
    Linux bridge
    使用 GDB 和 KVM 调试 Linux 内核与模块
    How To Set Up A Serial Port Between Two Virtual Machines In VirtualBox
    Linux内核调试环境搭建(基于ubuntu12.04)
    Android
  • 原文地址:https://www.cnblogs.com/NaLanZiYi-LinEr/p/11523304.html
Copyright © 2011-2022 走看看