• Head First设计模式(阅读笔记)-01.设计模式入门


    模拟鸭子


    使用继承?

    正常鸭子会有许多功能,比如飞行、游泳等。此时要生成多种不同的鸭子,马上想到的方法就是设计一个鸭子的父类,该父类中定义飞行、游泳等方法,然后让不同种类的鸭子去继承该父类即可。

    此时需要设计一个橡皮鸭,这个鸭子很明显并不会飞,但是因为父类中定义了fly方法,导致不具备该功能的子类需要去覆盖fly方法(这里如果不去覆盖该方法的话会有什么后果或缺陷吗?不是很理解),意味着代码量变多(尽管方法体中可以选择不写任何代码)并且重复


    使用接口?

    既然继承存在上述问题,那只在父类中定义所有鸭子的通用功能,再额外定义一个Flyable接口,让可以飞的鸭子实现Flyable接口不就可以了!确实不错,但是如果现在所有鸭子都具备飞行的功能,本来只需要父类实现fly方法就能搞定的事,现在需要每个子类都去重复实现一遍Flyable接口(简单而言就是代码无法复用),实在太麻烦了吧…


    使用策略模式

    介绍了直接使用继承和接口的弊端后,此时该设计模式登场了。这里直接透露下,下面代码使用到的是策略模式,先上代码:

    // 抽象的Duck类
    public abstract class Duck{
        FlyBehavior flyBehavior;
        public Duck{}
        public void setFlyBehavior(FlyBehavior fb){
            flyBehavior = fb; 
        }
        public void performFly(){
            flyBehavior.fly();
        }
        public void swim(){
            System.out.println("所有鸭子都会游泳的吧!");
        }
    }
    
    // FlyBehavior接口
    public interface FlyBehavior{
        public void fly();
    }
    // 飞行行为的实现类(可以飞和不能飞)
    // 1.FlyWithWings类
    public class FlyWithWings implements FlyBehavior{
    	public void fly(){
            System.out.println("I can fly!!!");
        }
    }
    // 2.FlyNoWay类
    public class FlyNoWay implements FlyBehavior{
    	public void fly(){
            System.out.println("I can't fly...");
        }
    }
    
    // 橡皮鸭-具体的实现类
    public class RubberDuck extends Duck{
        public RubberDuck(){
            flyBehavior = new FlyNoWay();
        }
    }
    
    // 测试代码
    public class Test{
        public static void main(String[] args){
            Duck rubberDuck = new RubberDuck();
            rubberDuck.performFly();  // 一开始橡皮鸭并不会飞,I can't fly...
            rubberDuck.setFlyBehavior(new FlyWithWings());
            rubberDuck.performFly();  // 现在突然会飞了,I can fly...
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    • FlyBehavior接口与其实现类:

      • 将应用中可能变化的地方与不需要变化的地方进行分离
      • 针对接口编程而不是针对实现编程:之前的方式是飞行行为的具体实现来自Duck类,或者是继承Flyable接口并由子类去实现。这里将Duck的子类只需要去使用接口表示的行为,具体实现并不会被绑定在子类中(比如代码中RubberDuck类只是调用performFly方法就完成了对飞行行为的表示)
    • Duck类:

      • 最大的改变是在该类中使用组合,即将飞行行为委托给FlyBehavior类,并不需要在类中去声明一个fly方法,Duck类也无需知道FlyBehavior类具体是如何实现飞行行为的
      • 为了能动态地设定飞行行为,使用到setter方法,在测试代码中可以很清晰看出,只要在setter方法中传入不同的FlyBehavior接口实现类即可
    • RubberDuck类:在该子类中,没有去实现接口,只是在构造函数中通过不同的引用(多态!)去定义不同的飞行行为而已

    参考

    Head First 设计模式-设计模式入门

  • 相关阅读:
    Java-接口、继承与多态
    亚马逊日本站坠落防护安全装备JIST8165标准怎么办理?
    设计模式之创建型模式:工厂模式
    J2EE--通用分页
    匿名页的反向映射
    SSM学习——数据源对象管理与加载properties文件(4)
    后端接口错误总结
    hdfs集群数据迁移/DataNode节点维护/集群重命名--小结
    九章云极DataCanvas大模型系列成果发布会重磅来袭,诚邀见证!
    CCRC认证是什么?
  • 原文地址:https://blog.csdn.net/qq_41398418/article/details/127946366