策略模式(设计原则)
其实说实话我不认为这是一种设计模式,他更重要的是带我们入门.并带出了几条设计原则出来,下面就让我们来看一下这几条原则都是什么.
- 找出应用中可能需要变化之处把它们独立出来,不要和那些不需要变化的代码放在一起.
- 要针对接口编程(其实学到后面我们还能看到面向超类(抽象类)编程)
- 多用组合,少用继承
举例说明
比如我现在有三个类,为了大家观看更方便,我将把所有类都写在一个代码块里面
public abstract class duck{
//叫
public void quack(){
System.out.println("呱呱叫");
}
//游泳
public void swim(){
System.out.println("自由泳");
}
//外观
public abstract void display();
}
//第一只鸭子
class duck1 extends duck{
@Override
public void display() {
System.out.println("我是蓝的");
}
}
//第二只鸭子
class duck2 extends duck{
@Override
public void display() {
System.out.println("我是绿的");
}
//下面还可能有1000只鸭子类
}
我们来仔细看上面的例子,如果有一天我们需要将鸭子添加一个会飞的功能,怎么办?
可能想直接在class duck()
类中添加一个fly()
方法
abstract class duck{
//叫
public void quack(){
System.out.println("呱呱叫");
}
//游泳
public void swim(){
System.out.println("自由泳");
}
//飞行
public void fly(){
System.out.println("飞行");
}
//外观
public abstract void display();
}
//第一只鸭子
class duck1 extends duck{
@Override
public void display() {
System.out.println("我是蓝的");
}
}
//第二只鸭子
class duck2 extends duck{
@Override
public void display() {
System.out.println("我是绿的");
}
}
//下面还可能有1000只鸭子类
当所有鸭子都有飞的功能这么写一点问题都没有,但是如果出现只有一部分鸭子有飞行功能,其他鸭子飞不起来,这样写肯定就会变得不合理,因为如果把
fly()
方法写在了超类里面,就意味着所有继承它的子类都拥有了fly()
方法,就意味着所有的鸭子都能飞起来了,那我们能不能将fly()
方法定义成抽象方法,如果鸭子能飞,就实现这个方法,如果不能飞实现这个方法的时候就什么都不写.
abstract class duck{
//叫
public void quack(){
System.out.println("呱呱叫");
}
//游泳
public void swim(){
System.out.println("自由泳");
}
//飞行
public abstract void fly();
//外观
public abstract void display();
}
//第一只鸭子
class duck1 extends duck{
@Override
public void fly() {
System.out.println("我是横着飞");
}
@Override
public void display() {
System.out.println("我是蓝的");
}
}
//第二只鸭子
class duck2 extends duck{
@Override
public void fly() {
}
@Override
public void display() {
System.out.println("我是绿的");
}
}
//下面还可能有1000只鸭子类
这样看似能解决当前的问题,但是还是有问题.
- 代码冗余,一个类里面有不需要实现的空方法,100只鸭子都是横着飞的,那么100只鸭子的实现就都是一模一样的.
- 代码冗余,必然带来维护上的麻烦,100只横着飞的鸭子,都需要改的话,就需要改100次.
其实正确的解决办法是将
fly()
方法从鸭子类中彻底脱离出来在用组合的方式将其结合起来
interface fly{
public void fly();
}
class fly1 implements fly{
@Override
public void fly() {
System.out.println("横着飞");
}
}
class fly2 implements fly{
@Override
public void fly() {
System.out.println("竖着飞");
}
}
abstract class duck{
//声明一个飞行类,这个就是我们上面说的组合,而非继承,这样降低耦合,
//并且也能缓解java只能继承一个类的尴尬
fly fly;
//我如何飞行是由fly的实现类决定的(java中的多态)
public void getFly(){
fly.fly();
}
//叫
public void quack(){
System.out.println("呱呱叫");
}
//游泳
public void swim(){
System.out.println("自由泳");
}
//外观
public abstract void display();
}
//第一只鸭子
class duck1 extends duck{
//子类构造器直接将超类中的fly赋值
duck1(){
super.fly = new fly1();
}
@Override
public void display() {
System.out.println("我是蓝的");
}
}
//第二只鸭子
class duck2 extends duck{
//子类构造器直接将超类中的fly赋值
duck2(){
super.fly = new fly1();
}
@Override
public void display() {
System.out.println("我是绿的");
}
}
//下面还可能有1000只鸭子类
你细细的品,上面的代码,如果我们想修改横着飞的步骤,我们只需要修改
fly1()
就可以,并且也解决了代码冗余的问题.这就是策略模式,实际上这更像是一种设计模式的入门思想.