前言
本系列设计模式的剖析主要基于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方法来进行接口的动态设置;
这样,策略模式就这样诞生;其中心思想就是对于可能会经常变化的东西,我们尽量使用接口来进行编程;满足我们“多用组合,少用继承”的设计原则,可以在运行时候动态地去改变行为;
网友评论