接触java、Android好长时间,常看一些前辈们写的代码,却发现很精辟。但是又很难理解。不久前看完了很多人推荐的《Head First Java》,此书很适合我这种的新人读,充分挖掘大脑,让我们更容易理解,并记忆。后来,在taobao搜了下Head First系列书籍,发现 《Head First 设计模式》这本书很畅销,好评如潮。买了一本后,读起来热血膨胀。理解前辈们代码为什么这么写。晚生以后常会将此书的观点整理给大家,如有错误请指出!
应用环境:
某公司要开发一个模拟鸭子的游戏,鸭子主要有 叫quack(),游泳swim(),行为display()方法。此公司为了在众公司脱颖而出,给鸭子duck实现飞fly(),功能。现在有以下几个方案:
方案一:用继承
public class Duck {
public void quack() {
}
public void swim() {
}
public void display() {
}
public void fly() {
}
}
public class MallardDuck extends Duck {
@Override
public void display() {
// 外观是橡皮鸭
}
@Override
public void quack() {
// 覆盖成吱吱叫
}
}
public class ReadHeadDuck extends Duck {
@Override
public void display() {
//外观是绿头
}
}
public class RubberDuck extends Duck {
@Override
public void display() {
// 外观是红头
}
}
问题:并不是所有的鸭子都会飞。改变会牵一发动全身,造成其他鸭子不想要的改变。————否决
方案二:用接口
问题:代码变得很多,如果有50个Duck子类都要修改行为,那怎么办?
设计原则一:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要的变化的代码混在一起。
此原则思考方式:把会变化的那部分“封装”起来,好让其他部分不会受到影响。
解决:我们知道Duck类内的fly()和quack()会随着雅子的不同而改变.为了要把这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为。
设计鸭子行为:
我们希望设计的 具有弹性,让鸭子的行为可以动态的改变。也就是,我们应该在鸭子类中包含设定行为的方法,这样就可以再“运行时”动态地“改变”绿头鸭的飞行行为。
设计原则二:针对接口编程,而不是针对实现编程。
从现在开始,鸭子的行为将被放在分开的类中,此类撰文提供某行为接口的实现。
针对接口编程和针对实现编程的比较。
Dog d = new Dog();
d.bark();
Animal animal = new Dog();
animal.makeSound();
public class Animal{
public void makeSound(){}
}
public class Dog extends Animal{
public void makeSound(){
bark();
}
public void bark(){
}
}
public class Cat extends Animal{
public void makeSound(){
meow();
}
public void meow(){
}
}
鸭子行为整合:
public abstract class Duck {
/**
* 行为接口类型声明两个引用变量,所有鸭子子类(在同一个package中)都继承它们
*/
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
public abstract void display();
/**
* 委托给行为类
*/
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float ,even decoys!");
}
}
//--------------------------------------------------------------------------------
/**
* 所有飞行必须实现的接口
*
*/
public interface FlyBehavior {
public void fly();
}
public class FlyWithWings implements FlyBehavior {
/**
* 飞行实现,给真会飞的鸭子用
*/
@Override
public void fly() {
System.out.println("I'm flying!!");
}
}
public class FlyNoway implements FlyBehavior {
/**
* 不会飞的鸭子用
*/
@Override
public void fly() {
System.out.println("I cat't fly!!");
}
}
//----------------------------------------------------------------------------------
public interface QuackBehavior {
public void quack();
}
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Squeak");
}
}
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
动态设定行为:
1.在duck类中加入两个新方法:
public void setFlybehavior(FlyBehavior fb){
flyBehavior=fb;
}
public void setQuackBehavior(QuackBehavior qb){
quackBehavior =qb;
}
2.制造一个新的鸭子类型:ModelDuck
public class ModeDuck extends Duck{
public ModelDuck(){
flyBehavior = new flyNoWay();
quackBehavior = new Quack();
}
public void display(){
Sysout.out.println("I'm a model duck");
}
}
3.建立一个新的FlyBehavior类型。
public class FlyRocketPowered Implements FlyBehavior{
public void fl(){
Sysout.out.println("I'm flying with a rocket!");
}
}
4.改变测试类。使模型鸭具有火箭动力。
public class MiniDuckSimulator{
public static void main(String[] args){
Duck model = new MallardDuck();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
类图如下:
组合:将两个类结合起来使用
设计原则三:多用组合,少用继承
刚才使用的设计模式就是:策略模式
策略模式定义了算法族,分别封装起来,让他们呢之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
组成: