Java设计模式——策略模式

最近看了郭霖大侠写的设计模式的博客,感觉收获很多,后来自己去看了《Head First设计模式》,也希望自己写一篇博客用来自己以后回顾。
先贴上郭大侠博客
假如有一天接到一个新的项目,要写一个关于飞机的软件。系统中飞机分为战斗机和轰炸机,两种飞机除了外貌不一样都可以飞行和战斗。稍微构思了一下,写出了这样的代码:


public class Plane
{
    public Plane()
    {
    }

    public void fight()
    {
        System.out.println("I can Fight!");
    }

    public void fly()
    {
        System.out.println("I can Fly!");
    }
}

public class Bomber extends Plane
{

    public Bomber()
    {
        System.out.println("I am Bomber!");
    }


}

public class Transport extends Plane
{
    public Transport()
    {
        System.out.println("I am Transport!");
    }

}

测试代码如下:


public class Test
{
    public static void main(String[] args)
    {
        Bomber bomber = new Bomber();
        bomber.fly();
        bomber.fight();
        Fighter fighter = new Fighter();
        fighter.fly();
        fighter.fight();
    }
}

测试结果:
I am Bomber!
I can Fly!
I can Fight!
I am Fighter!
I can Fly!
I can Fight!
然后有一天,版本更新了,系统中添加了一个不能战斗的飞机:运输机。稍微构思了一下添加了以下代码


public class Transport extends Plane
{
    public Transport()
    {
        System.out.println("I am Transport!");
    }


}
public class Test
{
    public static void main(String[] args)
    {
        Bomber bomber = new Bomber();
        bomber.fly();
        bomber.fight();
        Fighter fighter = new Fighter();
        fighter.fly();
        fighter.fight();
        Transport transport=new Transport();
        transport.fly();
        transport.fight();
    }
}

输出结果如下:
I am Bomber!
I can Fly!
I can Fight!
I am Fighter!
I can Fly!
I can Fight!
I am Transport!
I can Fly!
I can Fight!
通过输出的结果发现忘记了运输机是不能战斗的,稍微思考了一下之后,想到可以重写运输机的战斗方法fight来实现。这个时候开始犯难了,如果以后再增加其他的不能战斗的飞机或者不能飞机的飞机,都要检查并可能需要覆盖Fly和Fight。这在以后维护可能是一个大量的工作,而且可能会产生大量的重复代码。应该怎么办才好呢?
这时候应该使用设计模式“策略模式”。
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
我们知道并非所有的飞机都可以飞行或者战斗,所以继承并不是最适当的方式。虽然重写可以解决不能飞行或者不能战斗的方式,但是这样会产生重复代码,并且效率比较低。我们应该找应用中可能需要变化的地方,把他们独立出来,不要和那些不需要变化的代码混在一起。
我们可以把飞行和战斗作为个属性保存在飞机类里面,然后通过方法调用具体的实现类。


public interface Fly
{
    public void PlaneFly();
}
public interface Fighting
{
    public void PlaneFighting();
}

将这两个接口保存在飞机类里。通过fight和fly调用具体的实现,同时飞机的外貌可以由Introduction实现。


public abstract class Plane
{
    Fighting fighting;
    Fly fly;

    public abstract void Introduction();

    public void fight()
    {
        fighting.PlaneFighting();
    }

    public void fly()
    {
        fly.PlaneFly();
    }
}

Fly和Fight实现如下:


public class CanFight implements Fighting
{

    @Override
    public void PlaneFighting()
    {
        System.out.println("I can fighting!");

    }

}

public class CanFly implements Fly
{

    @Override
    public void PlaneFly()
    {
        System.out.println("I can Fly!");       
    }

}
public class CanNotFight implements Fighting
{

    @Override
    public void PlaneFighting()
    {
        System.out.println("I can't fighting!");

    }

} 
public class CannotFly implements Fly
{

    @Override
    public void PlaneFly()
    {
        System.out.println("I cannot Fly!");
    }

}

以上四个类就实现了是否可以飞行是否可以战斗四种情况。


public class Bomber extends Plane
{

    public Bomber()
    {
        fighting=new CanFight();
        fly=new CanFly();
    }

    @Override
    public void Introduction()
    {
        System.out.println("I am Bomber!");     
    }

}
public class Transport extends Plane
{

    public Transport()
    {
        fly = new CanFly();
        fighting = new CanNotFight();
    }

    @Override
    public void Introduction()
    {
        System.out.println("I am Transport!");

    }


}
public class Fighter extends Plane
{

    public Fighter()
    {

        fighting = new CanFight();
        fly = new CanFly();
    }

    @Override
    public void Introduction()
    {
        System.out.println("I am Fighter!");

    }


}

测试类如下


    Plane fighter = new Fighter();
        Plane transport = new Transport();
        Plane bomber=new Bomber();
        fighter.Introduction();
        fighter.fight();
        fighter.fly();
        transport.Introduction();
        transport.fight();
        transport.fly();
        bomber.Introduction();
        bomber.fight();
        bomber.fly();

结果如下:
I am Fighter!
I can fighting!
I can Fly!
I am Transport!
I can’t fighting!
I can Fly!
I am Bomber!
I can fighting!
I can Fly!
这样每种类别的飞机的功能就实现了,相互之间也没有什么影响,如果系统修改某个功能,只需要修改一个接口的实现类就Ok了。还可以通过一个小技巧动态修改飞机行为。首先在Plane添加Fly和Fight的set方法:

    public void setFighting(Fighting fighting)
    {
        this.fighting = fighting;
    }

    public void setFly(Fly fly)
    {
        this.fly = fly;
    }

测试方法如下:


    Plane transport = new Transport();
        for (int i = 0; i < 2; i++)
        {
            if (i==1)
            {
                transport.setFighting(new CanFight());
                transport.setFly(new CannotFly());
            }
            transport.fight();
            transport.fly();
        }

输出结果:
I can’t fighting!
I can Fly!
I can fighting!
I cannot Fly!

以上。
如有不对请指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值