zoukankan      html  css  js  c++  java
  • 继承和组合、单例类及不可变类

    江南骚年

    继承 inheritance:

    继承是实现类复用的重要手段,所谓复用,就是可以多次使用,或者再次利用,不用继续重写成员变量和方法。但不代表没有缺点,最不好的地方:破坏封装。子类拓展父类时,若访问权限允许,则可直接访问父类的成员变量和方法,破坏了良好的封装性(Encapsulation) ,造成子类与父类的耦合。

    因而,设计父类时应注意以下几点:

    • 尽量隐藏内部数据
    • 不要让子类随意访问
    • 不要在父类的构造器中调用将被子类重写的方法

    组合 combination

    对于继承而言,子类可以获取父类的public方法,使用子类时,可以访问子类从父类继承的方法;组合则是把旧类对象作为成员变量组合进来。我们不需要看到被组合进来的对象的方法,所以通常用private修饰。在功能上,两者没什么区别。

    class animal{
    	private void beat(){
    		System.out.println("心跳!");
    	}
        public void breath(){
            System.out.println("呼吸!");
        }
    }
    class bird{
        private animal a;
        public bird(animal){
            this.a = a;
        }
        public void breath(){
            a.breath();//复用animal的方法
        }
        public void fly(){
            System.out.println("芜湖起飞!");
        }
    }
    

    注意

    使用组合关系实现复用,需要创建两个animal对象,是否意味着开销更大?

    当创建一个子类对象时,系统不仅需要为该子类定义实例变量分配内存空间,而且需要为它父类所定义的实例变量分配内存。采用继承的方式,假设父类定义了两个实例的变量,子类定义了3个变量。创建子类实例时需要为子类分配5块内存空间。当采用组合设计时,先创建父类实例,此时需要分配2快内存,再创建整体类实例,也需要分配3块内存,只是多了一个引用变量来引用所组合的对象。因此,组合和继承设计开销不会有太大差别。

    单例类

    这种类不像其他类,某些时候允许其他类自由创建该类对象没有什么意义,所以要降低对它的访问权限,让这样的类只能创建一个实例。

    方法是把该类的构造方法用private修饰起来,但又需要创建一个对象,所以需要提供一个public方法去用于创建该类的对象,但是不是通过对象来创建对象,而是用类本身去创建,因此方法要用static修饰。

    除此之外,该类还必须缓存对象,记录已创建的对象。同时让该静态方法能访问到,保存对象的成员变量也需要static修饰。

    class person{
    	//静态成员变量来保存对象
        private static person OnlyPerson;
        //对构造器隐藏
        private person(){}
        //公共方法
        public static person getPerson(){
            if(OnlyPerson==null){
                OnlyPerson = new person();
            }
            return OnlyPerson;
        }
    }
    

    不可变类 immutable

    不可变类意思是创建该类的实例后,该实例的变量不可变。Java提供的8个包装类和String类都是不可变类!

    Double d = new Double(5.6);
    String s = new String("abc");
    

    上面创建了一个Double和String对象,并传入两个值,但程序无法继续修改该值,所以Double和String类没有修改值的方法。

    如果要创建一个不可变类,需要遵守如下规则:

    1. 使用privatefinal修饰符来修饰该类成员
    2. 提供带参构造器,用于初始化成员
    3. 仅提供get方法
    4. 确保引用的对象不会被修改
    5. 重写hashCode()方法和equals()方法

    与此对应的是可变类,比如JavaBean,提供了getter()和setter方法。

    缓存实例的不可变类

    不可变类的实例状态不可改变,可以方便被多个对象共享,主要是为了减小开销。不同的缓存方式有着不同的性能,可以用数组、集合等来缓存。

    以Java的java.lang.Integer类为例,new一个构造器,每次返回新的Integer对象;如果用valueOf()方法来创建Integer对象,则会缓存该对象。

    public class IntegerCacheTest{
    	public static void main(){
    		//new一个对象
    		Integer a1 = new Integer(6);
    		//生成新对象,并缓存该对象
    		Inreger a2 = Integer.valueOf(6);
    		Integer a3 = Integer.valueOf(6);
    		System.out.println(a1 == a2);//false
    		System.out.println(a2 == a3);//true
    		//注意:缓存的数只能在-128~127之间
    	}
    }
    

    公众号:菜鸡干Java

  • 相关阅读:
    洛谷P4979 矿洞:坍塌
    [SHOI2015]脑洞治疗仪
    洛谷P2135 方块消除
    洛谷P1436 棋盘分割
    洛谷P2796 Facer的程序
    浅谈位运算
    [SDOI2006]最短距离
    12耐心_预测未来
    11耐心_有效市场假说
    02C++条件变量
  • 原文地址:https://www.cnblogs.com/coderma/p/13687718.html
Copyright © 2011-2022 走看看