这是我看Head first设计模式书籍之后想要总结的知识点,一方面是对自己学习的东西总结和提炼加强自己的理解和记忆,另一方面是给大家简化这本书,方便大家快速了解各种设计模式。
我想提醒大家的是,设计模式只是前人总结的一些经验套路,实际上还是要在开发项目中慢慢体会,不可成为设计模式的中毒患者,强行照搬设计模式的一些规则。
我们这次要讲解的设计模式是策略模式
我们举个栗子:
我们设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。如果我们要更改需求,需要让鸭子可以飞翔,就在父类中添加了fly()方法,但是后来需求又变化了,我们要增加一个不会飞的鸭子来继承复用鸭子超类的一些方法,这样就产生了不会飞的鸭子飞翔的尴尬画面。
这时候通常大家的思路是:
1.虽然你可在不会飞的鸭子中覆盖父类的fly()方法,但是不会飞的鸭子一旦多了起来,那么代码就变得非常难以维护和重复。
2..增加Flyable接口,让子类鸭子实现这个接口,然后在类中实现这个fly()方法。但是这样,代码重复太多了。
我们的解决方法是:
将鸭子的飞行行为独立出来,定义一个FlyBehavior接口,然后用FlyWithWings等具体行为类实现此接口
我这里直接上代码:
Duck超类
public abstract class Duck{
//为行为接口类型声明两个引用变量,所有鸭子子类都继承它们
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck(){}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
//鸭子对象不亲自处理呱呱叫行为,而是委托给quackBehavior引用的对象
quackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float, event decoys!");
}
}
鸭子子类
public class MallardDuck extends Duck{
public MallardDuck(){
//quackBehavior是从父类继承来的
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
publicvoid display(){
System.out.println("I'm a real Mallard duck");
}
}
FlyBehavior接口与两个行为实现类FlyWithWings和FlyNoWay
//所有飞行行为类必须实现的接口
public interface FlyBehavior{
public void fly();
}
//这是飞行行为的实现
public class FlyWithWings implements FlyBehavior{
public void fly(){
System.out.println("I'm flying!!");
}
}
pulic class FlyNoWat implements FlyBehavior{
public void fly(){
System.out.println("I 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 class Squeak implements QuackBehavior{
public void quack(){
System.out.println("Squeak");
}
}
编译并测试
public class MiniDuckSimulator{
public static void main(String[] args){
/*这里使用了向上转型,不清楚的我简单说一下
因为子类是对父类的一并改进和扩大, 定义一个父类类型的引用指向一个子类的对象既可以使用子类
强大的功能,也可以抽取父类的共性。父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中
没有的方法,父类引用是无法调用的。*/
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
}
}
下面是总结的设计原则:
1.找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起
2.针对接口编程,而不是针对实现编程
3.多用组合,少用继承。比如将鸭子飞行独立出来。
策略模式:
定义了算法簇,分别封装起来, 让他们之间可以相互替换。此模式让算法的变化独立于使用算法的客户。