最近学习了设计模式方面的一些知识,感觉设计模式真的太重要了,深感之前写的代码就是渣啊,只是为了实现功能,一点复用性都没有,都是一次性代码,这个以后要改。
问题:以鸭子为例,我们关心它的几个属性:叫、吃、飞、外观。所有的鸭子都会叫、吃,但是并不是所有的鸭子都会飞,外观都有,但不同种类不一样。我们就简单设计A、B、C...类表示。
第一种方式:
1 public class ADuck{ 2 public void sing(){ 3 System.out.println("gua gua..."); 4 } 5 public void eat(){ 6 System.out.println("I love fish."); 7 } 8 public void color(){ 9 System.out.println("I am black."); 10 } 11 } 12 public class BDuck{ 13 public void sing(){ 14 System.out.println("gua gua..."); 15 } 16 public void eat(){ 17 System.out.println("I love grass"); 18 } 19 public void color(){ 20 System.out.println("I am yellow"); 21 } 22 }
这种方式就是典型的一次性代码。第二种实现方式:
1 public class Duck{ 2 public void sing(){ 3 System.out.println("gua gua..."); 4 } 5 public abstract void eat(); 6 public abstract void color(); 7 } 8 9 public class ADuck extends Duck{ 10 public void eat(){ 11 System.out.println("I love fish."); 12 } 13 public void color(){ 14 System.out.println("I am black"); 15 } 16 }
BDuck实现同理,这样就把功能相同的代码写在基类里,子类实现不一样的代码,从而实现了代码的复用。但是,这还是不够好的。
如果此时有了新需求,要加一个飞的功能。那么我们只能向下面这样在基类中添加了,不会飞的不实现该功能即可:
public class Duck{ public void sing(){ System.out.println("gua gua..."); } public abstract void eat(); public abstract void color(); public abstract void fly(); } public class ADuck extends Duck{ public void eat(){ System.out.println("I love fish."); } public void color(){ System.out.println("I am black."); } public void fly(){ System.out.println("I can fly.");//不会飞的该方法为空,不实现 } }
这样好像是能解决我们的问题,但是每次有新的需求都要修改基类,耦合太高,好像不是一个好的解决方式。
我们继续改进,把fly()方法放在一个接口里面,会飞的就继承该接口,不会飞的不继承即可。
1 public interface IFly{ 2 public void fly(); 3 } 4 public class Duck{ 5 public void sing(){ 6 System.out.println("gua gua..."); 7 } 8 public abstract void eat(); 9 public abstract void color(); 10 } 11 public class ADuck extends Duck implements IFly{ 12 public void eat(){ 13 System.out.println("I love fish."); 14 } 15 public void color(){ 16 System.out.println("I am black."); 17 } 18 public void fly(){ 19 System.out.println("I can fly."); 20 } 21 } 22 public class BDuck extends Duck{ 23 public void eat(){ 24 System.out.println("I love grass."); 25 } 26 public void color(){ 27 System.out.println("I am yellow."); 28 } 29 }
这样感觉好多了,但是接口并不会有具体实现,也就是不能复用,只能在每个继承的基类中具体去实现,那么就要用到策略模式了。
public interface FlyBehavior{ public void fly(); } public interface EatBehavior{ public void eat(); } public class FlyByWing implements FlyBehavior{ public void fly(){ System.out.println("I fly with my wings"); } } public class FlyNoWay implements FlyBehavior{ public void fly(){ System.out.println("I can not fly."); } } public class EatFish implements EatBehavior{ public void eat(){ System.out.println("I eat fish."); } } public class EatGrass implements EatBehavior{ public void eat(){ System.out.println("I eat grass."); } } public class Duck{ private FlyBehavior flyBehavior; private EatBehavior eatBehavior; public Duck{}; public void setFlyBehavior(FlyBehavior flyBehavior){ this.flyBehavior=flyBehavior; } public void setEatBehavior(EatBehavior eatBehavior){ this.eatBehavior=eatBehavior; } public void sing(){ System.out.println("gua gua..."); } public abstract void color(); public void fly(){ flyBehavior.fly(); } public void eat(){ eatBehavior.eat(); } } public class ADuck extends Duck{ public ADuck(FlyBehavior flyBehavior,EatBehavior eatBehavior){ this.setFlyBehavior(flyBehavior); this.setEatBehavior(eatBehavior); } public void color(){ System.out.println("I am black."); } }
上面的代码有什么好处呢,我们实现了多个继承自同一个接口的功能类,并且这些功能类与下面的具体类没有继承关系,耦合性非常低,而且这些功能我们在别的地方还可以复用,比如吃的功能,是动物类都会有的,是可以重复利用的。