[关闭]
@Tean 2016-06-05T08:19:40.000000Z 字数 2978 阅读 1936

Day10_面向对象(五)

Java


学习目标

  • 重点掌握内部类
  • 重点掌握单例模式
  • 重点掌握简单工厂模式

一、内部类

1.1 内部类概念

  • 将一个类定义在另一个类的里面,对于里面那个类就称为内部类内置类嵌套类)。
  • 如果在类Outer的内部再定义一个类Inner,此时Inner就称为Outer的内部类,而Outer则称为Inner的外部类。
  1. class Outer {
  2. class Inner {
  3. // TODO ...
  4. }
  5. }

1.2 内部类定义语法格式

语法:

  1. 修饰符 class 外部类名称 {
  2. // 外部类 属性 & 方法
  3. 修饰符 class 内部类名称 {
  4. // 内部类属性 & 方法
  5. }
  6. }

1.3 内部类特点

  1. 内部类可以被权限修饰符和static修饰。
  2. 内部类被权限修饰符修饰后,访问权限和其它成员变量、方法相同。
  3. 内部类可以访问外部类的成员,即使是私有的也可以访问。
  4. 被static修饰的内部类是静态内部类,只能访问外部类的静态成员。
  5. 内部类不能和它的外部类同名。

1.4 内部类分类

内部类可以分为:

  • 成员内部类(实例内部类)
  • 静态内部类
  • 局部内部类(内嵌内部类、方法内部类)
  • 匿名内部类
1.4.1 成员内部类
  • 成员内部类也称为实例内部类。
  • 成员内部类内不能声明静态变量和静态方法,但是可以定义静态常量。
  • 成员内部类持有外部类的对象,即先有外部类对象才可以创建内部类对象。
  • 在文件管理方面,成员内部类在编译完成后也会产生.class文件,而文件名称则是“外部类名称$内部类名称.class
  • 在外部类创建内部类对象的方法:
  1. Outer outer = new Outer(); //创建外部类对象
  2. Outer.Inner inner = Outer.new Inner(); //先有外部类对象才可以创建内部类对象。

内部类中可以用外部类名称.this.xxx调用外部类内容。

1.4.2 静态内部类
  • 如果一个内部类使用static修饰,则此内部类就称为静态内部类。
  • 访问静态内部使用 外部类名.内部类名
  • 创建静态内部类对象时,不必持有外部类对象,可以直接创建内部类对象。
  1. Outter.Inner inner = new Outter.Inner(); //直接创建内部类对象 Outer.new Inner();//错误
1.4.3 局部内部类
  • 局部内部类也叫内嵌内部类、方法内部类。
  • 局部内部类是定义在方法内的内部类,它的作用域只是该方法内,只能在该方法内部使用。所以局部内部类同方法内的局部变量一样,不能添加任何修饰符。
  • 局部内部类不能包含静态成员
  • 若在局部内部类中使用方法中的变量,则方法中的变量必须加final修饰(JDK8可不加)。
  1. public class Outer {
  2. /*
  3. * 在Inner内部类中使用了para参数和v变量,所有para和v必须用final修饰
  4. */
  5. public void fun(final int para) {
  6. final int v = 23;
  7. class Inner {
  8. public void method() {
  9. System.out.println(para);
  10. System.out.println(v);
  11. }
  12. }
  13. }
  14. }
1.4.4 匿名内部类
  • 如果一个内部类在整个操作中只使用一次的话,就可以定义为匿名内部类
  • 匿名内部类,这是Java为了方便我们编写程序而设计的一个机制,因为有时候有的内部类只需要创建一个它的对象就可以了,以后再不会用到这个类,这时候使用匿名内部类就比较合适。
  • 匿名类内部不用声明类名称,而是用new直接产生一个对象。匿名内部类是在抽象类和接口的基础上发展起来的。它可以是继承某个类,或是实现某个接口。
  • 比如:可以直接继承Object类定义一个匿名类,在重写toString方法后,用匿名类直接产生一个对象。
  • 在文件管理方面,内嵌匿名类编译后生成的.class文件的命名方式是“外部类名称$编号.class”,编号为1,2,3…n,编号为x的文件对应的就是第x个匿名类。
  1. {
  2. Object obj = new Object() {
  3. public String toString() {
  4. return "我们都是渣渣";
  5. }
  6. };
  7. System.out.println(obj); // 我们都是渣渣
  8. }

1.5 内部类的优缺点

  • 优点:
    1. 可以方便的访问外部类的私有属性
    2. 可以减小类编译后的大小
  • 缺点:
    1. 破坏了类的结构
    2. 降低了代码的可读性

二、单例模式

  • 对某个类,有时候我们只需要一个对象,而不允许有多个对象存在,这个时候我们可以把该类设计为单例模式。来满足我们的需求。
  • 一个不允许外界随意构造对象解决方案:
    1. 构造方法必须私有:外界无法构造对象
    2. 类内部提供一个静态方法,该方法返回该类的一个实例
  • 单例设计模式有两种表现形式:
    • 懒汉式
    • 饿汉式

2.1 懒汉式

  1. public class A {
  2. private static A a; // 定义静态的A类型的变量来储存内部创建的对象
  3. private A() { // 构造方法私有化
  4. }
  5. // 提供方法来获取A对象
  6. public static A getInstance() {
  7. if(a == null){ // 如果a == null 则创建一个对象,否则直接返回a指向的对象
  8. a = new A();
  9. }
  10. return a;
  11. }
  12. }
  13. // 懒汉式在多线程下存在问题,多线程时再对此代码进行改造

2.2 饿汉式

  1. public class A {
  2. private static A a = new A(); // 定义静态的A类型的变量来储存内部创建的对象
  3. private A() { //构造方法私有化
  4. }
  5. public static A getInstance() {
  6. return a;
  7. }
  8. }

三、简单工厂模式

3.1 概念

简单工厂模式(Simple Factory Pattern),又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。

3.2 优缺点

  • 优点:工厂类是整个模式的关键所在。它包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。有利于整个软件体系结构的优化。
  • 缺点:由于工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连;而且由于简单工厂模式的产品室基于一个共同的抽象类或者接口,这样一来,但产品的种类增加的时候,即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,这就和创建何种种类产品的产品相互混淆在了一起,违背了单一职责,导致系统丧失灵活性和可维护性。而且更重要的是,简单工厂模式违背了“开放封闭原则”,就是违背了“系统对扩展开放,对修改关闭”的原则,因为当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。

五、作业

  1. 定义一个乐器(Instrument)接口,其中有抽象方法 void play();
    在InstrumentTest类中,定义一个方法
    void playInstrument(Instrument ins);
    并在该类的main方法中调用该方法。
    要求:分别使用下列内部类完成此题。
    • 成员内部类
    • 局部内部类
    • 匿名类
  2. 定义一个Weapon,包含一个抽象方法shoot(),定义一个类Army,该类有一个静态方法attack(Weapow w),要求传一个Weapon对象做参数,表示让这个weapon对象发射。
    另外设计一个测试类,调用attack方法,要求:使用匿名内部类对象做参数进行传递。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注