前言
从今日起,陆续分享《HeadFirst设计模式》的读书笔记,希望能够帮助大家更好的理解设计模式,提高自己的编程能力。
设计模式本质上就是前人比较成熟的经验和智慧。他们遇到过相同的问题,也顺利地解决了这些问题。
跟随前人的脚步,可以少走弯路,也可以站在巨人的肩膀上看得更远。
使用模式最好的方式是:"把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。"以往是代码复用,现在是经验复用。
今天要分享的是【设计模式入门之策略设计模式】,希望对大家有所帮助。
设计模式入门之策略设计模式
书籍精彩内容
-
模拟鸭子
-
让鸭子飞
-
出问题了:橡皮鸭也会飞了
对代码所做的局部修改,影响层面可不只是局部(会飞的橡皮鸭)。
-
继承解决
弊端: 希望以后每六个月更新产品(至于更新的方法,他们还没想到)。Joe知道规格会常常改变,每当有新的鸭子子类出现,他就要被迫检查并可能需要覆盖fly()和quark()…这简直是无穷无尽的噩梦。
-
接口解决
弊端:重复代码变多,历史所有子类都得修改。
-
你怎么解决问题
-
软件开发真理
-
归零
-
设计鸭子的行为
-
针对接口编程
-
实现鸭子的行为
-
整合鸭子的行为
-
鸭子行为测试
-
动态设定行为
-
封装行为的大局观
-
设计模式
- 如何使用设计模式
- 为何要使用设计模式
- 如何使用设计模式
代码
- 第一版(出问题:橡皮鸭会飞)
/**
* 鸭子超类
*/
public abstract class Duck {
/**
* 呱呱叫
*/
public void quack() {
System.out.println("呱呱叫");
}
/**
* 游泳
*/
public void swim() {
System.out.println("游泳");
}
/**
* 鸭子外观
*/
abstract void display();
/**
* 鸭子其他方法...
* todo
*/
/**
* 飞行
*/
public void fly() {
System.out.println("飞行");
}
}
public class MallardDuck extends Duck {
@Override
public void display() {
System.out.println("我的外观是绿头");
}
}
public class RedheadDuck extends Duck {
@Override
public void display() {
System.out.println("我的外观是红头");
}
}
public class RubberDuck extends Duck {
@Override
public void display() {
System.out.println("我的外观是橡皮");
}
@Override
public void quack() {
System.out.println("吱吱叫");
}
@Override
public void fly() {
// 什么都不做,不会飞
}
}
public class DecoyDuck extends Duck {
@Override
public void display() {
System.out.println("我的外观是诱饵");
}
@Override
public void quack() {
// 什么都不做,不会叫
}
@Override
public void fly() {
// 什么都不做,不会飞
}
}
public class RubberDuckTest {
@Test
public void display() {
RubberDuck rubberDuck = new RubberDuck();
rubberDuck.quack();//见鬼了:橡皮鸭也会叫了
//解决:覆盖超类方法为吱吱叫
}
}
- 第二版:继承和接口解决
public interface Flyable {
void fly();
}
public interface Quackable {
void quack();
}
public abstract class Duck {
public void swim() {
System.out.println("游泳");
}
abstract public void display();
}
public class MallardDuck extends Duck implements Flyable, Quackable {
@Override
public void display() {
System.out.println("我的外观是绿头");
}
@Override
public void fly() {
System.out.println("飞");
}
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
public class RedheadDuck extends Duck implements Flyable, Quackable {
@Override
public void display() {
System.out.println("我的外观是红头");
}
@Override
public void fly() {
System.out.println("飞");
}
@Override
public void quack() {
System.out.println("嘎嘎叫");
}
}
public class RubberDuck extends Duck implements Quackable {
@Override
public void display() {
System.out.println("外观是橡皮鸭");
}
@Override
public void quack() {
System.out.println("吱吱叫");
}
}
public class DecoyDuck extends Duck {
@Override
public void display() {
System.out.println("我的外观是诱饵");
}
}
- 第三版:策略设计模式解决(封装变化,代码灵活且耦合性低)
面向实现编程,而不是面向接口编程
public abstract class Animal {
abstract void makeSound();
}
public class AnimalFactory {
public static Animal getAnimal(Animal animal) {
if (animal instanceof Dog) {
return new Dog();
} else if (animal instanceof Cat) {
return new Cat();
}
return null;
}
}
public class Cat extends Animal {
public void makeSound() {
meow();
}
public void meow() {
System.out.println("喵喵叫");
}
}
public class Dog extends Animal {
public void makeSound() {
bark();
}
public void bark() {
System.out.println("汪汪叫");
}
}
public class AnimalTest {
@Test
public void makeSound() {
//针对实现编程
Dog dog = new Dog();
dog.bark();
//针对接口编程
Animal animal = new Dog();
animal.makeSound();
Objects.requireNonNull(AnimalFactory.getAnimal(new Dog())).makeSound();
}
}
第三版会飞的鸭子解决方案:
public interface FlyBehavior {
void fly();
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly");
}
}
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying!!");
}
}
public interface QuackBehavior {
void quack();
}
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>");
}
}
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void setFlyBehavior(FlyBehavior fb) {
this.flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
this.quackBehavior = qb;
}
public void swim() {
System.out.println("All ducks float, even decoys");
}
public abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
public class MallardDuck extends Duck {
public MallardDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
ModelDuck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
图例
- 会飞的鸭子第一版
- 会飞的鸭子第二版
- 会飞的鸭子第三版
术语
- OO:Object Oriented(面向对象)
- 超类:superclass
- 子类:subclass
- 模拟:simulate,软件可以模拟现实世界,比如会飞的鸭,网购等
- 类图:可以展示类之间的关系,比如继承、实现、依赖等
- 复用:reuse
工具箱
茶话会
收获
1.如何查看超类实现
ctrl+h
2.uml类图如何画
1)idea自动生成
https://blog.csdn.net/qq_52302333/article/details/131341626
非社区版的,diagrams自带就有该功能,社区版需要安装插件
plantUML:https://plantuml.com/zh/
simpleUML:https://cloud.tencent.com/developer/article/2428172 【无插件,需要离线安装】
2)手绘
通过starUML
3.brew查看安装软件位置
brew info graphviz
4.查看mac隐藏文件夹
command+shift+.
5.软件迭代的原则:对现有功能影响降低到最小,最好不影响
知识点回顾与总结
- 1.会飞的鸭子问题解决方案演进
- 2.策略设计模式的介绍
- 3.一些OO原则:
- 封装变化
- 多用组合,少用继承(I have a 而不是I’m a)
- 针对接口编程,不针对实现编程