《Effective java》读书记录-第20条-类层次优于标签类

下面的类,它能够表示圆形或者矩形。

public class Figure {
    enum Shape { RECTANGLE,CIRCLE };

    //Tag field - the shape of this figure
    final Shape shape;

    //These fields are used only if shape is RECTANGLE
    double length;
    double width;

    //This field is used only if shape is CIRCLE
    double radius;

    //Constructor for circle
    Figure(double redius){
        shape=Shape.CIRCLE;
        this.radius=radius;
    }

    //Constructor for rectangle
    public Figure (double lenght,double width) {
       shape=Shape.RECTANGLE;
        this.length=lenght;
        this.width=width;
    }

    double area(){
        switch (shape){
            case RECTANGLE:return length*width;
            case CIRCLE:return Math.PI*(radius * radius);
            default:throw new AssertionError();
        }
    }
}

这种标签类(tagged class)有着许多的缺点。它们中充斥着样板代码,包括枚举声明、标签域以及条件语句。

多个实现乱七八糟地挤在了单个类中,破坏了可读性

增加了内存的占用,因为实例承担着属于其他风格的不相关域。

域不能做成final的,除非构造器初始化相关的域,如果不需要初始化相关于,那就会需要增加更多的样板代码。

无法给标签类添加风格,除非可以修改它的源文件,如果一定要添加风格,就必须记得给每个条件语句都添加一个条件,否则类就会在运行时失败。

实例的数据类型没有提供任何关于其风格的线索。

标签类过于冗长、容易出错,并且效率低下


怎么来表示多种风格对象的单个数据类型?

子类化。标签类正是类层次的一种简单的仿效


既然标签类的问题那么多,那么这么把标签类转换为类层次?

1、将标签类中的方法(需要用标签来区别的方法)定义成抽象类中的抽象方法。

2、在子类中定义属于该类的数据域。

如下,将Figure标签类

abstract class Figure{
        abstract double area();
    }

    class Circle extends Figure{
        final double radius;

        Circle(double radius){this.radius=radius;}

        double area(){return Math.PI*(radius*radius);}
    }
    
    class Rectangle extends Figure{
        final double length;
        final double width;
        
        Rectangle(double length,double width){
            this.length=length;
            this.width=width;
        }
        
        double area(){return length*length;}
        
    }

 将成类层次后,就纠正了标签类的所有缺点。同时方便程序员独立地扩展层次结构,并且不用访问根类的源代码就能相互操作。

类层次还有一个好处,增强灵活性,方便编译时类型检查。类层次能够很好的反映类型之间本质上的层次关系。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值