设计模式入门
从一个鸭子类切入。一个鸭子对象可以拥有下列行为
- 叫
- 飞
- 外形
- 游泳
一系列的行为,如果只是单纯的创建一个父类,父类中实现上述的四个方法,让所有的子类鸭去实现,当需要改变需求的时候,对于代码的改动就比较大(不是所有的鸭子都会飞,都会叫等等),复用性比较差。
这里涉及到了几个设计原则 - 找出应用中可能变化的地方,把他们独立出来
- 针对接口编程,不要针对实现编程
- 多用组合,少用继承
因此,把这个鸭子类中的可能变的方法抽取出来,抽取两个接口,代码如下
package com.chapter.one;
public interface FlyBehavior {
void fly();
}
package com.hundsun.chapter.one;
public interface QuackBehavior {
void quack();
}
上面两个接口把可以抽取出来的行为抽取出来,单独封装成接口。为了可以让不同的鸭子实现不同的行为
这样鸭子类代码如下
package com.chapter.one;
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
void swim(){
System.out.println("all duck can swim");
}
//父类中动态的注入行为
void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
void setQuackBehavior(QuackBehavior quackBehavior){
this.quackBehavior = quackBehavior;
}
abstract void disPlay();
public void quack(){
quackBehavior.quack();
}
public void fly(){
flyBehavior.fly();
}
}
鸭子类中的叫, 和飞 方法由于不是所有的鸭子都可以的方法, 因此定义两个接口类型的对象。借由接口来实现这两个方法。
接口的具体实现可以自行发挥,实现飞,和叫的具体实现.这里要注意,Duck类中的具体行为接口并没有初始化在子类实现中要实现初始化
package com.chapter.one;
public class MallardDuck extends Duck{
//初始化行为提供者
public MallardDuck() {
flyBehavior = new FlyWithWing();
quackBehavior = new Quack();
}
@Override
void disPlay() {
System.out.println("i am MallardDuck");
}
}
在构造方法中,对接口进行实现,在调用父类方法的时候,调用接口的实现进行实现具体的方法。