ü  设计原则1:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
例如:对于一个鸭子类,不同的鸭子(真鸭子,木头鸭子等)有不同的飞行行为,呱呱叫行为,所以要把这两个行为从鸭子类中分离出来,在鸭子类中只保存那些不变的部分。
《Head.First设计模式读书笔记》之设计原则一、二和三_设计
 
ü  设计原则2:针对接口编程而不是针对实现编程。
这里的接口有多个含义,它可以是java中的interface,也可以是抽象类。“针对接口编程”,关键就在多态。利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上。“针对超类型编程”这句话,可以更明确地说成“变量的声明类型应该是超类型,通常是一个抽象类或者是一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量
举个例子:
《Head.First设计模式读书笔记》之设计原则一、二和三_《Head.First设计模式读书笔记》_02
假设有一个抽象类Animal,其下有两个实现类 DogCat继承自Animal。做法如下:
² 针对实现编程:
Dog dog = new Dog();
bj.bark();
注:声明变量“dog Dog类型(Animal的具体实现),会造成我们必须针对具体实现编码。
² 针对接口/抽象类编程:
Animal animal = new Dog();
Animal.makeSound();
注:利用animal进行多态的调用。
 
设计原则3:多用组合(composition),少用继承
使用组合建立系统具有很大的弹性,不仅可将行为封装成类,更可以“在运行时动态地改变行为,只要组合的行为对象符合正确的接口标准即可。
 
    例如:在设计原则一中我们把“飞行行为”和“呱呱叫行为”这两个变化的行 为从鸭子类中分离出来。这里我们就设计这两个行为和鸭子类:
《Head.First设计模式读书笔记》之设计原则一、二和三_设计_03
以上     以上为两个行为接口和它的实现类。此时我们要做的就是把两个行为整合到鸭子类中,具体怎么整合?继承吗?继承只能继承一个特定的类,因此用继承将不能“在运行时动态地改变行为”。那么我们选用组合。
        Duck类中“加入两个实例变量”,分别为“flyBehavior”与“quackBehavior”,声明为接口类型(而不是具体类实现类型),每个鸭子对象都会动态地设置这些变量以在运行时引用正确的行为类型(例如:FlyWithWingsSqueak等)《Head.First设计模式读书笔记》之设计原则一、二和三_设计_04
 
此时我们就把两个行为组合到Duck类中了,既然使用了组合,我们怎么在运行时动态地改变行为呢?如下我们写一个main函数来看看:
    public static void mian(String args[]){
       Duck duck = new Duck();
       duck.setFlyBehavior(new FlyNoWay());
       duck.setQuackBehavior(new Quack());
       //此时若想要鸭子能飞,我们可以通过setter方法在运行时动态地改变行为
       duck.setFlyBehavior(new FlyWithWings());
    }
         Sping中依赖注入(IOC)使用的就是组合。