JAVA05-多态和策略模式

Java中的多态,多态时面向对象的灵魂,是最重要的特性

 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
public class Main {
    public class Base {
        public void sayHello() {
            System.out.println("Hello");
        }
    }

    public class Sub extends Base {
        @Override
        public void sayHello() {
            System.out.println("你好");
        }
    }

    public static void main(String[] args) {
        /*
        虽然你用的是父类类型变量,但它实际是子类类型的对象
        因此this等于Sub类型的对象,因此实际调用的是sub对象的sayHello方法
        这就是面向对象的多态性
               
        几个例子,例如HashSet.addAll方法,由于HashSet本身并没有addAll方法
        因此它调用的是它父类的addAll方法,在父类的addAll方法中,又调用了add(这一点
        可以跟踪HashSet源码看到),那么到这里你肯定会觉得它调用的是父类自己的add方法,
        但其实调用的是HashSet的add方法,因为this是HashSet
              
        还比如你可能经常见到这种用法:
          List list = new ArrayList(); 这些都是用到了多态的特性
        */
        Base base = new Sub();
        base.sayHello();
    }
}

什么是多态

  1. 在运行时根据this是谁,来决定调用谁的方法
  2. 实例方法默认是多态的
  3. 静态方法没有多态特性
  4. 参数也没有多态特性

设计模式之策略模式,策略模式依赖继承和多态性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Main {
    /**
     * 有这么一个需求,给定一个产品的名字,返回它的价格
     * 下面的实现方式有什么弊端? 如何优化?
     * @param name 产品名
     * @return 返回这个产品的价格
     */
    public static int getPrice(String name) {
       /*
       这个实现不好,因为未来每加一个产品,你都需要添加一个case语句,
       这样会造成你的代码又臭又长,我们可以通过策略模式来解决它
       */
        switch (name) {
            case "MacBook":
                return 14999;
            case "iPhone":
                return 8999;
            default:
                return 0;
        }
    }
}

我们可以抽取共性,将返回价格的策略提取成一个类,这个例子策略就是产品名字,我们通过产品名来返回相应的价格

 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
50
51
52
53
54
55

/**
 * 产品类,基类,它有一个返回产品价格的方法
 * 实际上这个可以换成接口,不过现在还没学到接口,以后再说了
 */
public class Product { 
    /**
     * @return 返回这个产品的价格
     */
    public int discount() {
        return 0;
    }
}

/**
 * MacBook类,它继承了产品类,并重写了discount方法,用于返回MacBook自己的价格
 */
public class MacBook extends Product {
    private static final int PRICE = 14999;

    @Override
    public int discount() {
        return PRICE;
    }
}

/**
 * iPhone类,它继承了产品类,并重写了discount方法,用于返回iPhone自己的价格
 */
public class IPhone extends Product {
    private static final int PRICE = 8999;

    @Override
    public int discount() {
        return PRICE;
    }
}

public class Main {
    /**
     * 这里就利用了多态性来实现策略的分发
     * 虽然这里的参数是Product类型,但由于向上转型可知,我们可以传递子类对象进来
     * 又因为多态性,this指向的是子类对象,所以调用的是子类的discount方法
     * @param product 产品类
     * @return 返回这个产品的价格
     */
    public static int getPrice(Product product) {
        return product.discount();
    }

    public static void main(String[] args) {
        System.out.println(getPrice(new MacBook()));
        System.out.println(getPrice(new IPhone()));
    }
}

需要注意的点

  1. 涉及金额的时候,绝对不可以用double

因为double是不精确的,它是一个近似值而不是绝对值

  1. 你应该使用BigDecimal类型,因为它是精确的
updatedupdated2025-03-012025-03-01