(个人笔记,不喜勿喷,欢迎指正~)
一、概念
策略模式:定义算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。(恩,书上是说这句话是用来和面试官装x的,哈哈~)
个人理解
策略模式,就是把会变化的内容变成由外部装配的接口A,不再由内部实现业务。然后将变化的内容进行分类抽象,实现接口A,变成一组精简,可复用的装配对象集合An{A1,A2,A3,...}。由具体需求、具体场景选择An集合中的任意一个实例对接口A进行装配。
二、设计原则
1、找出应用中的变化之处,对立出来,拒绝和不变的代码混在一起。
2、针对接口编程,而不是针对实现编程。
3、少用继承,多用组合。
个人理解
原则1:略过,
原则2:JAVA面向对象开发,最小单位是类,软件是类与类之间相互作用的产物,而类的成员方法,便是类交互的接口;所以我们设计原则2,意思就是,设计时,我们要抽象的去看待,由类实例变化而发生改变的接口(成员方法),理解他们实现的职能,不应该关心如何去实现这些变化。
原则3:设计模式书中提到设计父类鸭子的“飞行”和“叫”动作,不同种类的鸭子存在能力的差异,但大多数还是存在相同,倘若我们通过父类继承实现,那我们就得从在每个子类中重新定义实现,那我们需要书写许多重复的内容。因此,我们从父类继承的不应该是行为的实现,而是行为的能力。即为"飞行能力"和“叫的能力”;行为的实现应由各自实例引用装配,很好的体现了运行时动态改变状态这一特点。这就是为什么我们抽象基类的设计时,存在差异变化的接口(成员方法)选择组合。
三、is-a 与 has-a 的关系
is - a “是一个”,向上抽象解释,说明事物上层的本质。例如:狗是一种动物;
has - a “有一个” 具备属性解释。例如:鸭子有飞行种能力。
四、代码实现
/**
* 发生行为组合接口
*/
public interface SoundBehavior {
void makeSound();
}
/**
* 汪星人叫法
*/
public class Bark implements SoundBehavior {
@Override
public void makeSound() {
System.out.println("我们一起学狗叫,一起喵旺旺旺~");
}
}
/**
* 喵星人叫法
*/
public class Meow implements SoundBehavior {
@Override
public void makeSound() {
System.out.println("我们一起学猫叫,一起喵喵喵喵~");
}
}
/**
* 动物基类
*/
public abstract class Animal {
//动物具备发生属性
private SoundBehavior sounding;
//setter为属性装配接口
public void setSounding(SoundBehavior sounding) {
this.sounding = sounding;
}
//发生行为接口
public void makeSound(){
sounding.makeSound();
}
public abstract void display();
}
/**
* 猫星人
*/
public class Cat extends Animal{
@Override
public void display() {
System.out.println("别看了,你还不如妹子手上的猫咪呢~");
}
}
/**
* 汪星人
*/
public class Dog extends Animal {
@Override
public void display() {
System.out.println("别看了,知道你也是只单身狗,不泡妞,"
+ "才会撸代码的。");
}
}
/**
* 测试
*/
public class StrategyPatternTest {
public static void main(String[] args) {
Animal wangcai =new Dog();
wangcai.setSounding(new Bark());
wangcai.makeSound();
wangcai.display();
Animal tom =new Cat();
tom.setSounding(new Meow());
tom.makeSound();
tom.display();
}
}
测试输出
五、总结
关于策略模式模式,还是比较印象深刻的,做过的一个项目的模块,写一个下载驱动,当时抽象基类,自己选择了继承的方式去写,现在想想,似乎策略模式比较实用合理,下载的途径就应该是可选的,ftp,http等,下载的数据如果只是存储,继承影响不大,但是往往我们下载的内容,样本数据下载完成回调时,进行文本分析处理。似乎我们需要对不同的文本,装配我们自己写好的处理策略方案。这样会让代码更精简,机动灵活。
(ps:第一次写博客,学会怎么去表达,会让我们更深刻的去理解内容。记得以前有个大大说过,写博客是为了让自己的思想和经验固化。很赞同~)