场景模拟
Joe的公司做了一套模拟鸭子的游戏,游戏中会出现各种鸭子,可以一遍游泳戏水,一边呱呱叫。系统采用标准的OO技术,类图如下:
因为公司处于上升期,所以需要开发个牛逼的类型的鸭子,将竞争者甩在后头:会飞的鸭子。Joe毕竟是个OO程序员,这对他没什么难度
这样呢,就实现了红头、绿头会飞的鸭子,效果还不错哦!!
在股东会议上,由于之前Jack在程序中加入了一款橡皮鸭子,这个鸭子只是一种摆设鸭子,所以呢它不会飞,但可以发出吱吱的叫声,这样的话,屏幕上就出现了个可怕的场景:橡皮鸭子在飞!!!,股东很不开心!!
![](https://i-blog.csdnimg.cn/blog_migrate/cdd8127682065d37fefd8ffd0c1af497.png)
Joe想到的解决方法呢,依旧是继承,橡皮鸭子不能叫,那在子类覆盖默认实现就好!
可是,之后若要再加入一种诱饵鸭,它既不会叫,也不会飞,该如何?按照上述的方法,又得覆盖queck()和fly()方法
Joe发现,在之前的继承中方案中,每当有新的鸭子出现时,他都要去检查fly()和quack()方法,这简直是无穷无尽的噩梦
重新整理思路,Joe觉得改用接口实现的方式去做
那么新的问题又来了:公司需要加入48种会飞的鸭子,Joe要手动实现了48个子类的fly()方法!而且其中大多数fly的方式都是大同小异,这样代码量明显增大!
思考:
1、继承并不是适当的解决方式
2、抽取Flyable和Quackable接口能解决一部分问题,让子类实现接口,会造成代码无法复用
重新整理思路:
抽取Flyable和Quackable接口能解决一部分问题,但因为无法复用代码,那么需要一种方法,能够解决这一问题
新的设计原则:
把会变化的部分抽取出来进行封装,一般以后可以改动或扩充,从而不会影响不需要变化的部分
针对接口编程,而不是针对实现编程
之前的做法是,鸭子飞行、叫声的行为都来自超类的实现,或者是子类实现接口并有子类自行去实现,这两种实现都是依赖于实现编程
正确做法:针对接口编程,这里的接口,可以是一个抽象类或一个接口
在这种新的设计中,实际的实现,不会绑死在鸭子的子类中,具体的实现在FlyBehavior的实现类中,同理QuackBehavior也是一样
修改后
多用组合(HAS-A),少用继承(IS-A)
其实上述的就是策略模式
策略模式定义:定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户
面向对象的准则:
1、封装变化
2、多用组合,少用继承
3、针对接口编程,不针对实现编程
具体代码实现:
抽象出Duck抽象类,以及FlyBehavior接口和QuackBehavior接口
public interface FlyBehavior {
void fly();
}
public interface QuackBehavior {
void quack();
}
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public abstract void dispaly();
public void peformFly() {
flyBehavior.fly();
}
public void peformQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("所有的鸭都能浮在水面哦!诱饵鸭也行的!");
};
}
FlyBehavior各实现类
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("我会飞哦,超开心的!!");
}
}
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("我不会飞!!!好难过!!");
}
}
QuackBehavior各实现类
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("呱呱呱呱叫!");
}
}
public class Squeak implements QuackBehavior{
@Override
public void quack() {
System.out.println("吱吱吱吱叫!");
}
}
public class MuteQuack implements QuackBehavior{
@Override
public void quack() {
System.out.println("我不会叫!!好忧伤!!");
}
}
各类鸭的实现
public class MallarDuck extends Duck{
public MallarDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void dispaly() {
System.out.println("我是绿头鸭~~!");
}
}
public class RubberDuck extends Duck{
public RubberDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
@Override
public void dispaly() {
System.out.println("我是橡皮鸭~~!");
}
}
public class DecoyDuck extends Duck{
public DecoyDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new MuteQuack();
}
@Override
public void dispaly() {
System.out.println("我是诱饵鸭~~!");
}
}
public class RedheadDuck extends Duck{
public RedheadDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void dispaly() {
System.out.println("我是红头鸭~~!");
}
}
模拟调用:
调用:
Duck mallarDuck = new MallarDuck();//创建绿头鸭
mallarDuck.dispaly();//显示绿头鸭外观
mallarDuck.swim();//绿头鸭游泳啦!
mallarDuck.peformFly();//绿头鸭飞行!
mallarDuck.peformQuack();//绿头鸭呱呱叫
输出的结果:
我是绿头鸭~~!
所有的鸭都能浮在水面哦!诱饵鸭也行的!
我会飞哦,超开心的!!
呱呱呱呱叫!
调用:
Duck rubberDuck = new RubberDuck();//创建橡皮鸭
rubberDuck.dispaly();//显示橡皮鸭外观
rubberDuck.swim();//橡皮鸭游泳啦!
rubberDuck.peformFly();//橡皮鸭不会飞!
rubberDuck.peformQuack();//橡皮鸭吱吱叫
输出的结果:
我是橡皮鸭~~!
所有的鸭都能浮在水面哦!诱饵鸭也行的!
我不会飞!!!好难过!!
吱吱吱吱叫!
调用:
Duck decoyDuck = new DecoyDuck();//创建诱饵鸭
decoyDuck.dispaly();//显示诱饵鸭外观
decoyDuck.swim();//诱饵鸭游泳啦!
decoyDuck.peformFly();//诱饵鸭不会飞!
decoyDuck.peformQuack();//诱饵鸭不会叫!
输出的结果:
我是诱饵鸭~~!
所有的鸭都能浮在水面哦!诱饵鸭也行的!
我不会飞!!!好难过!!
我不会叫!!好忧伤!!
Android中的策略模式
Android中的ListView的setAdapter()方法中的参数ListAdapter就用到了策略模式
接口及实现类如下:
public interface ListAdapter extends Adapter {}
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {}
public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter()
ListView的setAdapter()方法如下:
public void setAdapter(ListAdapter adapter)
可以看到 ListAdapter 是一个接口,ArrayAdapter 和 BaseAdapter 是它的实现类。 ListView 中的setAdapter()参数ListAdapter对象可根据子类动态传入具体的对象