阅读HeadFirst设计模式(一)

由于最近在看设计模式的东东,今天又把以前看过的 HeadFirst设计模式资料拿出来看了看。  
现将今天看的总结下,后面会相应的更新...

现在开始:
    情景一:
        现在比如鸭子有两种--MallardDuck,RedheadDuck,它们都会呱呱叫、游泳,但外观是不一样的。代码设计如下:
    
鸭子基类(Duck)

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。
我们会在Duck类中直接添加fly()方法,然后所有鸭子都会飞了。
现在Duck的代码如下
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("鸭子可以飞了!");
	}

但这里忽略了一件事,并不是所有的鸭子都会飞!
现在我们添加一个新的鸭子类--RubberDuck(橡皮鸭):
public class RubberDuck extends Duck {
	
	@Override
	public void quack() {
		System.out.println("橡皮鸭只会吱吱叫!");
	}

	@Override
	public void fly() {
		//不会飞,所以覆盖父级中的方法
	}

	@Override
	public void display() {
		System.out.println("橡皮鸭!");
	}

}

这样看来可以暂时满足,橡皮鸭的“需求”,但如果我又添加一种新的鸭子,那怎么办?
先不如我们把fly,quack分别创建两个不同的接口吧!
Flyable
public interface Flyable {
	void fly();
}

Quackable
public interface Quackable {
	void quack();
}

这样一来,只要有fly,quack的鸭子才去实现这两个接口,但新的问题又出现了,这样固然解决了一些问题(橡皮鸭现在不会飞了),但现在这样无法将代码复用。
此时,你可能期盼着设计模式来解救你!

到这一步,我们见到了设计模式的第一个原则:
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

就目前所知,Duck除了fly(),quack()的问题之外,其他还算正常。
现在我们就把这些“变化和不变化的部分”分开(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();

上面的例子其实就用了设计 模式中的策略模式。

你可能感兴趣的:(java,设计模式,策略,Headfirst)