设计模式1——策略模式
这次阅读HeadFirst这本书的读书笔记,就想把学到的写成博客与之分享, 第一次写博客,如有错误欢迎纠错。
1.1定义
定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
1.2引例(模拟鸭子应用)
需求: 系统中会出现很多鸭子,一边游泳,一边呱呱叫
1.2.1 通过超类和继承设计
其他不同的鸭子也像图中的两种鸭子一样,继承Duck超类。
每个鸭子子类负责实现自己的display()
方法。
可以看出鸭子:
共同点:①游泳 ②呱呱叫。
不同点:外表不同。
实现方式:通过继承超类Duck,其中超类中quack()
和swim()
方法都是相同,在超类Duck中进行实现。display()
方法不同的鸭子子类实现方式不同,因此将display()
方法设计为抽象类。
追加需求:提高竞争力,要求鸭子会飞。
1.2.2 超类增加方法
做法:直接在超类增加fly()
方法。
问题:屏幕上很多橡皮鸭也在飞,不是所有鸭子都会飞。
1.2.3 利用接口解决
做法:将fly和quack动作单独提取出来,做成接口:flyable
和quackable
接口。换句话讲就是将鸭子共同的特点保留在超类,将不同的特点进行提取做成不同的接口。不同鸭子的子类根据需实现相应的接口。
问题:如果是fly的方式有很多,可以用翅膀,飞行器等等,quack方式也有很多,比如呱呱叫,吱吱叫等等,这样设计会出现大量的代码需要改写。
恰好现在有一种设计原则适用于这个问题。
设计原则:找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混合在一起。
1.2.4 设计鸭子的行为
1.分析鸭子的行为
找出变化的和不会变化的行为。可以看出鸭子会变化的行为目前有两个:fly和quack。不会变的行为是swim,所有的鸭子都会游泳。从图4中可以看出,fly和quack行为不单单只有一种,
2.设计鸭子的行为
设计原则:针对接口编程,而不是针对实现编程。
这次不让鸭子的子类去实现行为的接口,而是用不同的行为类去实现这些接口。
以前是的做法是让超类去实现或者使用接口让子类自行实现,这两种做法都依赖于“实现”。设计没有弹性。
现在的设计不会被“实现”绑死。换句话说,具体的实现都编写在了实现FlyBehavior和quackBehavior的类中。
1.2.4 总设计
(1)Duck超类变成抽象类,又添加了两个成员变量,FlyBehavior和QuackBehavior两个。
(2)增加4个方法:performFly()
,performQuack()
,setFlyBehavior()
和setQuackBehavior()
。
(3)两个perform方法分别调用接口中的fly()
和quack()
方法。 两个set方法是分别设置两个成员变量FlyBehavior和QuackBehavior。
(5)将display()
方法作为抽象方法进行使用。
(6)其他鸭子的子类通过继承Duck超类,并在构造方法中设置成员变量。以MallardDuck构造方法为例,这样MallardDuck就实现了不会飞,呱呱叫的行为。
MallardDuck (){
flyBehavior=new FlyNoWay();
quackBehavior=new Quack();
}
图6中的封装飞行行为和封装叫行为都有不同的实现,这就避免了面对“实现”编程,通过组合来编程,这样更加灵活。
设计原则:多用组合,少用继承。
1.3代码
(1)Duck 抽象类:
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float,even decoys");
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
(2) 鸭子子类(只写了两个子类实现)
//MallardDuck 子类
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out.println("I am a real Mallard duck");
}
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
}
}
//ModelDuck 子类
public class ModelDuck extends Duck {
public ModelDuck(){
flyBehavior=new FlyNoWay();
quackBehavior=new Quack();
}
public void display() {
System.out.println("I am a model duck");
}
public static void main(String[] args) {
Duck model =new MallardDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
(3) FlyBehavior 接口及行为类
//FlyBehavior 接口
public interface FlyBehavior {
void fly();
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can not fly");
}
}
//添加了一个用火箭飞行的行为
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I am flying with a rocket");
}
}
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I am flying");
}
}
(4)QuackBehavior接口及行为类
//QuackBehavior接口
public interface QuackBehavior {
void quack();
}
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence>>");
}
}
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack!");
}
}
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}