策略模式
面向对象的基础包括:继承、封装、多态、抽象
模拟鸭子的应用:
其中,使用继承的好处是能够实现代码的复用,如
有时,我们可以使用接口解决这样的问题(分开会变化和不会变化的部分,会变化的作为接口使用),如
现在我们知道使用继承和接口都无法很好地解决问题
而关键在于鸭子的行为quack()会随着鸭子的不同而改变
显现我们面对的问题是“如何分开会变化和不会变化的部分”
使用策略模式可以解决这个问题,我们需要将会变化的部分分离出来并封装起来
策略模式:定义算法族并封装起来,让它们能够互相替换,使算法的变化独立于使用算法的客户
代码演示:
当我们需要再添加一种新的鸭子,并且这种鸭子又有了新的飞行行为(新策略)时,我们可以这样
设计原则1------把会变化的部分取出来并封装起来
当新的需求到来时会使某部分的代码发生改变,我们可以确定这部分的代码为可变部分
此处是将Duck的fly()行为和quack()行为分离出来
设计原则2------针对接口编程而不是针对实现编程
使用多态,将变量的声明类型设计为超类型(抽象类或接口)
此处是声明FlyBehavior flyBehavior接口和QuackBehavior quackBehavior接口
设计原则3------多用组合少用继承
使用组合(有一个)可能比使用继承(是一个)更好
此处是将FlyBehavior行为和QuackBehavior行为设计为组合而不是使用继承来实现
参考书籍《Head First 设计模式》
模拟鸭子的应用:
其中,使用继承的好处是能够实现代码的复用,如
public abstract class Duck
{
public void quack(){}
public void swim(){}
public void fly(){}
public void otherbehavior(){}
}
public class Greenheadduck extends Duck{}
public class Redheadduck extends Duck{}
然而,并非所有的继承都是有用的,有时我们需要用到覆盖,如
public class Woodduck extends Duck
{
//木头鸭子不能嘎嘎叫
pubilic void quack(){}
//覆盖此方法,但是什么也不做
}
显然,每次加入一种新的鸭子后,继承并不能解决所有问题,我们需要不断的进行覆盖有时,我们可以使用接口解决这样的问题(分开会变化和不会变化的部分,会变化的作为接口使用),如
public abstract class Duck
{
public void swim(){}
public void otherbehavior(){}
}
public interface quackable
{
public void quack();
}
public class Redheadduck extends Duck implements quackable
{
public void quack()
{
System.out.println("嘎嘎叫");
}
}
public class Woodduck extends Duck implements quackable
{
pubilic void quack()
{
System.out.println("不会叫");
}
}
然而,使用接口却无法实现代码的复用,而且当鸭子的新种类越来越多时,使用接口无异于覆盖现在我们知道使用继承和接口都无法很好地解决问题
而关键在于鸭子的行为quack()会随着鸭子的不同而改变
显现我们面对的问题是“如何分开会变化和不会变化的部分”
使用策略模式可以解决这个问题,我们需要将会变化的部分分离出来并封装起来
策略模式:定义算法族并封装起来,让它们能够互相替换,使算法的变化独立于使用算法的客户
代码演示:
//第一种策略
public interface First_Strategy
{
public void algorithm_one();
}
public class FStrategy_one implements First_Strategy
{
public void algorithm_one()
{
System.out.println("FStrategy_one's algorithm_one");
}
}
public class FStrategy_two implements First_Strategy
{
public void algorithm_one()
{
System.out.println("FStrategy_two's algorithm_one");
}
}
//第二种策略
public interface Second_Strategy
{
public void algorithm_two();
}
public class SStrategy_one implements Second_Strategy
{
public void algorithm_two()
{
System.out.println("SStrategy_one's algorithm_two");
}
}
public class SStrategy_two implements Second_Strategy
{
public void algorithm_two()
{
System.out.println("SStrategy_two's algorithm_two");
}
}
/*------第N种策略------*/
public abstract class Client
{
//可变部分分离为接口变量
First_Strategy firststrategy;
Second_Strategy secondstrategy;
public void use_First_Strategy()
{
firststrategy.algorithm_one();
}//使用第一种策略算法
public void use_Second_Strategy()
{
secondstrategy.algorithm_two();
}//使用第二种策略算法
}
public class Client_one extends Client
{
public Client_one()
{
firststrategy = new FStrategy_one();
secondstrategy = new SStrategy_one();
}
}//定义客户一及其需要使用的策略
public class Client_two extends Role
{
public Client_two()
{
firststrategy = new FStrategy_two();
secondstrategy = new SStrategy_two();
}
}//定义客户二及其需要使用的策略
public class StrategyPatternDemo
{
public static void main(String[] args)
{
Client one = new Client_one();
Client two = new Client_two();
one.use_First_Strategy();
two.use_First_Strategy();
one.use_Second_Strategy();
two.use_Second_Strategy();
}
}
鸭子实例:
public interface FlyBehavior
{
public void fly();
}
public class FlyWithWings implements FlyBehavior
{
public void fly()
{
System.out.println("flying");
}
}
public class FlyNoWay implements FlyBehavior
{
public void fly()
{
System.out.println("can't fly");
}
}
public interface QuackBehavior
{
public void quack();
}
public class Quack implements QuackBehavior
{
public void quack()
{
System.out.println("Quack");
}
}
public class MuteQuack implements QuackBehavior
{
public void quack()
{
System.out.println("Silence");
}
}
public abstract class Duck
{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void swim(){}
public void otherbehavior(){}
public void performQuack()
{
flyBehavior.fly();
}
public void performFly()
{
quackBehavior.quack();
}
}
public class MallardDuck extends Duck
{
public MallardDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}//野鸭子
}
public class ModelDuck extends Duck
{
public ModelDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyNoWay();
}//模型鸭子
}
public class Demo
{
public static void main(String args[])
{
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
model.performQuack();
model.performFly();
}
}
另外,使用了策略模式不仅可以解决问题,而且可以实现动态设定行为
当我们需要再添加一种新的鸭子,并且这种鸭子又有了新的飞行行为(新策略)时,我们可以这样
public abstract class Duck
{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void swim(){}
public void otherbehavior(){}
public void performQuack()
{
flyBehavior.fly();
}
public void performFly()
{
quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior fb)
{
flyBehavior = fb;
}//新增加的方法,用于动态设定行为
}
public class FlyRockPowered implements FlyBehavior
{
public void fly()
{
System.out.println("flying with a rocket");
}
}//新增加的策略
public class Demo
{
public static void main(String args[])
{
Duck model = new ModelDuck();
model.performQuack();
model.performFly();//更改行为前print:"can't fly"
model.setFlyBehavior(new FlyRockPowered);
model.performFly();//更改行为后print:"flying with a rocket"
}
}
策略模式的设计原则:
设计原则1------把会变化的部分取出来并封装起来
当新的需求到来时会使某部分的代码发生改变,我们可以确定这部分的代码为可变部分
此处是将Duck的fly()行为和quack()行为分离出来
设计原则2------针对接口编程而不是针对实现编程
使用多态,将变量的声明类型设计为超类型(抽象类或接口)
此处是声明FlyBehavior flyBehavior接口和QuackBehavior quackBehavior接口
设计原则3------多用组合少用继承
使用组合(有一个)可能比使用继承(是一个)更好
此处是将FlyBehavior行为和QuackBehavior行为设计为组合而不是使用继承来实现
参考书籍《Head First 设计模式》