策略模式的定义:
策略模式:定义了算法族(函数组),分别封装起来,让他们之间可以互相替换,此模式让算法(函数)的变化独立于使用算法(函数)的客户。
结合日常生活来理解,例如:我们需要一些桌子,但是桌子的颜色,形状等全然不知。
/**
* 策略模式
* @author Vio.wang
*
* ex: 现在需要一些桌子
*
* 桌子的外形 可能为圆形 方形 长方形 等
* 桌子的颜色 可能为黄色 绿色 灰色 等
*
* 桌子的功能 放东西
*
*/
abstract class BaseTable{
String shape;
String color;
void display() {
System.out.println("I‘m a "+ color +" table.");
}
void placeThing(){
System.out.println("I can place some things.");
};
}
/**
* 红桌子
* @author Vio.wang
*
*/
class RedTable extends BaseTable{
void display() {
shape = "round";
color = "red";
super.display();
}
}
/**
* 绿桌子
* @author Vio.wang
*
*/
class GreenTable extends BaseTable{
void display() {
shape = "round";
color = "green";
super.display();
}
}
这么做,我们就可以很快的按照标准来生产出红桌子,绿桌子等。
利用继承实现桌子特殊功能:
但是,现在我们需要一个可以办公的桌子,但是并不是所有的桌子都可以用来办公。接下来该如何设计呢?
可以在BaseTable中加入 dealBusiness(),不具备办公工作的桌子覆盖dealBusiness(), 什么事也不做。
以上利用继承来实现table的行为有很多的缺点:
1.代码在多个子类中重复
2.运行时的行为不容易改变
3.很难知道桌子具备的全部功能
4.改变会牵一发动全身,造成其他的桌子强行改变
所以继承并不适合解决这种需求,造成的代码无法复用,甚至办公的行为也可能有许多不同的需求。这真是个循环的噩梦。
设计原则:把会变化的部分取出来并封装起来,好让其他的部分不受影响。
优势:代码变化引起的不经意后果变少,系统变得更有弹性。
这样,我们需要讲桌子的办公行为独立出来,重新设计桌子的行为。
设计原则:针对借口编程,而不是针对实现编程。
什么是针对接口编程:
class Dog extends Animal {
void makeSound() {
super.makeSound();
System.out.println("wang~");
}
}
Dog dog = new Dog();
dog.makeSound();
这就是面向实现编程
Animal animal = new Dog();
animal.makeSound();
这才是面向接口编程,利用多态,我们只需要对象
public static Animal getAnimal(String animal){
if (animal.equals("dog")) {
return new Dog();
}
if (animal.equals("cat")) {
return new Animal();
}
return null;
}
getAnimal("dog").makeSound();
我们不关心实际子类型是什么 只关心如何正确的makeSound即可。
我们看看面向接口是如何做的:
例如:鸟类,都是会唱歌,会飞,但是有部分鸟还会游泳。我们如何完成对鸟类的设计呢?
/**
* 游泳的接口 定义了游泳的行为
* @author Vio.wang
*
*/
interface SwimInter {
void swim();
void swimNoWay();
}
abstract class Bird {
SwimInter swimInter;
abstract void display();
abstract void sing();
// 在这里我们将游泳的行为委托给swimInter的对象 当swimInter被调用时 也就实现了鸟的游泳行为
public void performSwim() {
swimInter.swim();
};
/**
* 可随时改变实现 改变游泳的行为
* @param inter
*/
public void setSwimInter(SwimInter inter){
swimInter = inter;
}
}
class Seagull extends Bird {
public Seagull() {
swimInter = new SwimInter() {
public void swimNoWay() {
}
public void swim() {
System.out.println("I can swim~~~");
}
};
}
void display() {
System.out.println("I‘m a seagull~~~");
}
void sing() {
System.out.println("o~~~");
}
}
Bird bird = new Seagull();
bird.performSwim();
// 可随时改变对SwinInter的实现 从而改变海鸥的游泳行为
bird.setSwimInter(new SwimInter() {
public void swimNoWay() {
}
public void swim() {
System.out.println("I can swim so fast~~~");
}
});
bird.performSwim();
在这里使用了委托的形式实现了海鸥的游泳行为。
就像是,人会飞。没错,我们不会飞,但是我们会制造飞机。
我们将飞这件事委托给了飞机。
设计原则:多用组合,少用继承。
版权声明:本文为博主原创文章,未经博主允许不得转载。