java基础学习之多态和策略模式

java三大特性:继承、封装、多态.

今天学习一下多态, 多态的三要素:

继承、重写(overWrite区别于overLoad)、父类引用指向子类对象.

多态的基础是继承, 先来复习一下继承.

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

继承的特性:

  • 子类拥有父类非private的属性,方法。

  • final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写。

  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

  • 子类可以用自己的方式重写父类的方法。

  • Java的继承是单继承,但是可以多重继承

继承的关键字extends, java中所有的类都继承Object类,Object类拥有的方法HashCode(); wait(); notify(); equals(); getClass(); toString(); clone(); finalize()

构造方法:

    通过多态的方式实例无参对象,首先要调用父类的无参构造方法,再调用子类的无参构造方法

@Data
public class Shape {

    public Shape() {
        System.out.println("这里什么形状");
    }

}




@Data
public class Triangle extends Shape {

    public Triangle() {
        System.out.println("这是三角形");
    }

}


public static void main(String[] args) {

    Shape shape1 = new Triangle();

    }

//结果是先调用父类无参构造再调用子类无参构造


D:\java\jdk1.8\bin\java.exe ...
这里什么形状
这是三角形

Process finished with exit code 0

    

    通过多态的方式实例有参对象,首先要调用父类的无参构造方法,再调用子类的有参构造方法

@Data
public class Shape {

    public String length = "什么形状的长";

    public String width = "什么形状的宽";

    public Shape() {
        System.out.println("这里什么形状");
    }

}



@Data
public class Triangle extends Shape {

    public String length = "三角形的长";

    public String width = "三角形的高";

    public Triangle() {
        System.out.println("这是三角形");
    }

    public Triangle(String length, String width) {
        this.length = length;
        this.width = width;
        System.out.println("这是一个长是" + length + ", 宽是" + width + "的三角形");
    }

}




public static void main(String[] args) {
//通过有参构造实例对象
    Shape shape = new Triangle("这应该是什么形状的长","这应该是什么形状的宽");

    }

//结果先调用父类无参构造,再调用子类的有参构造

D:\java\jdk1.8\bin\java.exe ...
这里什么形状
这是一个长是这应该是什么形状的长, 宽是这应该是什么形状的宽的三角形

Process finished with exit code 0

    

    子类是不继承父类的构造方法的,它只是调用。

    如果父类只有有参构造,没有手动加无参构造, 则子类的有参构造必须显式地通过 super 关键字调用父类的有参构造。

@Data
public class Shape {

    public String length = "什么形状的长";

    public String width = "什么形状的宽";


    public Shape(String length, String width) {
        this.length = length;
        this.width = width;
        System.out.println("这是一个长是" + length + ", 宽是" + width + "的不明形状");
    }

}


@Data
public class Triangle extends Shape {

    public String length = "三角形的长";

    public String width = "三角形的高";

    public Triangle(String length, String width) {
        super(length, width); //这里要手动去调父类的构造方法
        this.length = length;
        this.width = width;
        System.out.println("这是一个长是" + length + ", 宽是" + width + "的三角形");
    }

}



 public static void main(String[] args) {
     Shape shape = new Triangle("这应该是什么形状的长","这应该是什么形状的宽");

    }


//结果先调用父类有参构造,再调用子类有参构造

D:\java\jdk1.8\bin\java.exe ...
这是一个长是这应该是什么形状的长, 宽是这应该是什么形状的宽的不明形状
这是一个长是这应该是什么形状的长, 宽是这应该是什么形状的宽的三角形

Process finished with exit code 0

    如果父类有无参构造,则在子类不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

注意的点: 

    通过多态实例对象时, 编译时成员变量和方法要看父类,如果父类没有的话不会通过jvm的编译.

    1. 将父类的成员变量注释掉,  将父类的静态和非静态方法也都注释掉, 我们通过多态的实例去调用这些变量或者方法, 结果:  不能通过编译.

     代码如下:

@Data
public class Shape {

//    public String length = "什么形状的长";

//    public String width = "什么形状的宽";

//    public static String angle = "有几个角";

    public Shape() {
        System.out.println("这里什么形状");
    }

//    public static void calculatedArea(String length, String width){
//        System.out.println("面积 = " + length + "×" +  width);
//    }

//    public void special(){
//        System.out.println("点");
//    }

}



@Data
public class Triangle extends Shape {

    public String length = "三角形的长";

    public String width = "三角形的高";

    public static String angle = "三个角";

    public Triangle() {
        System.out.println("这是三角形");
    }

    public static void calculatedArea(String length, String width) {
        System.out.println("面积 = 1/2 × " + length + "×" +  width);
    }

    public void special(){
        System.out.println("三角形");
    }

}



5ef5f839c25109d4f16d56e41ae015e62e0.jpg

 

2. 我们再把父类注释的都打开, 然后发现可以通过编译, 输出结果如下:

@Data
public class Shape {

    public String length = "什么形状的长";

    public String width = "什么形状的宽";

    public static String angle = "有几个角";

    public Shape() {
        System.out.println("这里什么形状");
    }

    public static void calculatedArea(String length, String width){
        System.out.println("面积 = " + length + "×" +  width);
    }

    public void special(){
        System.out.println("点");
    }

}



@Data
public class Triangle extends Shape {

    public String length = "三角形的长";

    public String width = "三角形的高";

    public static String angle = "三个角";

    public Triangle() {
        System.out.println("这是三角形");
    }


    public static void calculatedArea(String length, String width) {
        System.out.println("面积 = 1/2 × " + length + "×" +  width);
    }

    public void special(){
        System.out.println("三角形");
    }

}




     public static void main(String[] args) {
        Shape shape = new Triangle();
        String angle = shape.angle;
        System.out.println("角: " + angle);
        System.out.println("长: " + shape.length);
        System.out.println("宽: " + shape.width);
        shape.calculatedArea("100", "200");
        shape.special();

    }


D:\java\jdk1.8\bin\java.exe ...
这里什么形状
这是三角形
角: 有几个角
长: 什么形状的长
宽: 什么形状的宽
面积 = 100×200
三角形

Process finished with exit code 0

输出结果可以看出: 成员变量都是父类的结果, 静态方法是父类的结果, 非静态方法是子类的结果.

因此, 多态实例对象时,  在编译时成员变量和方法都看父类, 父类没有则编译报错, 父类有则可以通过编译;  运行的时候, 成员变量和静态方法是父类的结果, 非静态方法则是子类的结果.

所以, 子类中的独有方法(没有通过重写父类的方法), 那么就不能通过多态实例的对象来调用该方法. 多态一定要有重写

多态中我们还涉及到, 类型转换: 向上转型(隐式、自动转型),  向下转型(显式、强制转型) . 向下转型有风险,有可能数据溢出, 丢失精度. 使用时需要注意.

多态的好处是可扩展性高, 灵活性

 

策略模式:它定义了算法,分别封装起来,让他们之间可以替换,此模式让算法的变化,不会影响到算法的客户。

java中 treeset 和 treemap 的排序功能是采用的策略模式的思想 我们只需要自己定义排序字段、规则就可以

策略模式的优点

  (1)策略模式提高代码的复用性, 避免重复
  (2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。

策略模式的缺点

  (1)必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着必须理解这些算法的区别,以便适时选择恰当的算法类。
      (2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很多。

设计原则

  设计原则是把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。

  策略模式属于对象行为型模式,主要针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响其他代码情况下发生变化。策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。

策略模式中有三个对象

  (1) 环境对象:该类中实现了对抽象策略中定义的接口或者抽象类的引用。

  (2) 抽象策略对象:它可由接口或抽象类来实现。

  (3) 具体策略对象:它封装了实现同不功能的不同算法。

  利用策略模式构建程序,可以根据用户配置情况,选择不同有算法来实现应用程序的功能。具体的选择由环境对象来完成。采用这种方式可以避免由于使用条件语句而带来的代码混乱,提高应用程序的灵活性与条理性。

转载于:https://my.oschina.net/u/4149810/blog/3066122

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值