由于最近在看设计模式的东东,今天又把以前看过的 HeadFirst设计模式资料拿出来看了看。
现将今天看的总结下,后面会相应的更新...
public abstract class Duck { public void quack(){ System.out.println("鸭子都会呱呱叫!"); } public void swim(){ System.out.println("鸭子都会游泳!"); } public abstract void display(); }
红头鸭(RedheadDuck)
public class RedheadDuck extends Duck { @Override public void display() { System.out.println("红头鸭!"); } }
野鸭(MallardDuck)
public class MallardDuck extends Duck { @Override public void display() { System.out.println("野鸭的外观是绿头!"); } }
现在情况有些变化,我们要让鸭子能够fly。
public abstract class Duck { public void quack(){ System.out.println("鸭子都会呱呱叫!"); } public void swim(){ System.out.println("鸭子都会游泳!"); } public abstract void display(); public void fly(){ System.out.println("鸭子可以飞了!"); }
但这里忽略了一件事,并不是所有的鸭子都会飞!
public class RubberDuck extends Duck { @Override public void quack() { System.out.println("橡皮鸭只会吱吱叫!"); } @Override public void fly() { //不会飞,所以覆盖父级中的方法 } @Override public void display() { System.out.println("橡皮鸭!"); } }
这样看来可以暂时满足,橡皮鸭的“需求”,但如果我又添加一种新的鸭子,那怎么办?
public interface Flyable { void fly(); }
Quackable
public interface Quackable { void quack(); }
这样一来,只要有fly,quack的鸭子才去实现这两个接口,但新的问题又出现了,这样固然解决了一些问题(橡皮鸭现在不会飞了),但现在这样无法将代码复用。
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
就目前所知,Duck除了fly(),quack()的问题之外,其他还算正常。
“呱呱叫”接口:QuackBehavior
public interface QuackBehavior { void quack(); }
Quack(默认的叫法)
public class Quack implements QuackBehavior { @Override public void quack() { System.out.println("鸭子呱呱叫!"); } }
Squeak(橡皮鸭的叫法)
public class Squeak implements QuackBehavior { @Override public void quack() { System.out.println("鸭子吱吱叫!"); } }
MuteQuack(哑鸭)
public class MuteQuack implements QuackBehavior { @Override public void quack() { //什么都不做,不会叫! } }
“飞”的接口:FlyBehavior
public interface FlyBehavior { void fly(); }
FlyNoWay(不会飞的)
public class FlyNoWay implements FlyBehavior { @Override public void fly() { //什么都不做,不会飞! } }
FlyWithWings(用翅膀飞)
public class FlyWithWings implements FlyBehavior { @Override public void fly() { System.out.println("用翅膀来飞行!"); } }
最后我们的Duck变成了下面这样的:
public abstract class Duck { private FlyBehavior flyBehavior; private QuackBehavior quackBehavior; public void swim(){ System.out.println("鸭子都会游泳!"); } public void performQuack(){ quackBehavior.quack(); } public void performFly(){ flyBehavior.fly(); } public abstract void display(); public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } public void setQuackBehavior(QuackBehavior quackBehavior) { this.quackBehavior = quackBehavior; } }
PS:上面我们认识了第二个设计原则:
针对接口编程,而不是针对实现!
接口并非真正的interface,关键是在多态。也可以理解为针对超类编程。这样就不用写死,可以在运行中根据实际情况执行真正的行为,方法。
多用组合,少用继承!
Duck duck = new RubberDuck(); duck.setFlyBehavior(new FlyNoWay()); duck.performFly();
上面的例子其实就用了设计 模式中的策略模式。