day_14_内部类,单例模式,工厂模式
一 .当一个事物的内部,还有一个部分需要一个完整的结构进行描述
- 而这个内 部的完整的结构又只为外部事物提供服务
- 那么整个内部的完整结构最好使 用内部类
- java中一个类的定义位于另一个类内部,前者为内部类,后者为外部类
- 内部类重要作用 : 可以访问外部类的私有化数据
- 变量 :
-
成员变量 : 成员内部类(对象调用)
-
静态变量 : 静态内部类(类名,变量名)
-
局部变量 : 局部内部类
-
形参和实参变量 : 匿名内部类
- 成员内部类 :
-
1 可以等同看做成员变量
-
2 成员内部类中不能有静态声明
-
3 成员内部类中可以直接访问外部类所有的属性
public class _01_OuterClass {
private static String s1 = "A";
private String s2 = "B";
// private,public,protected 都可以使用
// 编译后的类名为 外部类类名$内部类类名
// _01_OuterClass$InnerClass
class InnerClass {
// 不能有静态声明
// static int x = 2;
// public static void m1(){ }
public void m2(){
// 可以直接访问外部类的所有属性
System.out.println(s1);
System.out.println(s2);
}
}
public static void main(String[] args) {
// 创建外部类对象
_01_OuterClass oc = new _01_OuterClass();
// 通过外部类对象去创建成员内部类对象
InnerClass ic = oc.new InnerClass();
ic.m2();
}
1.静态内部类
-
1 可以看做静态变量
-
2 静态内部类中,不能直接访问成员数据,需要有对象才行
-
3 静态内部类中可以声明所有东西
public class _02_OuterClass {
private static String s1 = "A";
private String s2 = "B";
// 静态内部类
private static class InnerClass{
public static void m1(){
System.out.println(s1);
// 不能直接访问成员属性
// System.out.println(s2);
// 需要用对象调用
_02_OuterClass s = new _02_OuterClass();
System.out.println(s.s2);
}
public void m2(){
System.out.println(s1);
// 不能直接访问成员属性
// System.out.println(s2);
}
}
public static void main(String[] args) {
// 外部类.内部类.静态
_02_OuterClass.InnerClass.m1();
// 访问当前类的静态属性的时候,类名可以省略(外部类)
InnerClass.m1();
InnerClass ic = new _02_OuterClass.InnerClass();
InnerClass ic1 = new InnerClass();
ic.m2();
}
}
2.局部内部类等同于局部变量
//
// 局部内部类 在访问外部方法中的局部变量的时候需要加final修饰(可省略)
//
// 局部内部类中,不能有静态声明
//
// 如果是成员方法中的局部内部类,可以访问外部类中所有的属性
//
// 如果是静态方法中局部内部类, 不可以直接访问外部类的成员属性
public class _01_OuterClass {
private static String s1 = "A";
private String s2 = "B";
public static void main(String[] args) {
_01_OuterClass oc = new _01_OuterClass();
oc.m1();
m2();
// TODO Auto-generated method stub
}//静态方法
public static void m2(){
int i = 2;
class InnerClass{
//不能有静态声明
//报错public static void m3(){}
public void m3(){
System.out.println(s1);
//不能直接访问外部类的成员属性
//System.out.println(s2);
//船舰对象的时候访问
_01_OuterClass a = new _01_OuterClass();
System.out.println(a.s2);
System.out.println(new _01_OuterClass().s2);
System.out.println(i);
}
}
//调用
InnerClass ic = new InnerClass();
ic.m3();
}
//成员方法
public void m1(){
final int i = 10;
//不能加权限控制甫
class InnerClass{
// public static void m3(){}
public void m4() {
System.out.println(s1);
// 因为是成员方法中的局部内部类,所以可以直接访问外部类中的所有属性
System.out.println(s2);
//可以不加final修饰,但是 值依然不能更改
System.out.println(i);
}
}
//调用,只能在方法内调用
InnerClass ic = new InnerClass();
ic.m4();
}
}
3.匿名内部类
- 匿名内部类 : 指在方法调用时,实参需要传入某个接口对象的时候,不传入对象,传入一个匿名的实现类
- 如果方法定义形成 一般是个接口,那么调用的时候,就需要传入其实现类的对象
- 但是可以不实现这个接口,不传递实现类对象,传递一个匿名内部类,这个类,没有名字,不能复用
- 默认的匿名内部类类名 : 外部类类名$1 一次类推
- 由于匿名内部类我们无法创建对象,但是传入时会自动创建一个对象
public class _02_OuterClass {
public static void main(String[] args) {
ICustomerService cs = new CustomerServiceImpl();
m1(cs);
// 匿名内部类写法
// 少定义一个类
// 但是无法重复使用
m1(new ICustomerService() {
int i = 2;
@Override
public void logout() {
System.out.println("已退出登陆" + this);
}
});
m2(new A(){
// 等于是创建了一个A的子类,并覆写了m3方法
public void m3(){
System.out.println("sssssss");
super.m3();
}
});
// TODO Auto-generated method stub
}
public static void m1(ICustomerService cs) {
cs.logout();
}
public static void m2(A a) {
a.m3();
}
}
interface ICustomerService {
public void logout();
}
class CustomerServiceImpl implements ICustomerService {
@Override
public void logout() {
System.out.println("已退出登陆");
}
}
class A{
public void m3(){
System.out.println("===");
}
}
二,单例模式
单例模式 : 只让某个类创建一个对象
*
- 实现步骤 :
-
首先我们要控制创建对象的数量,就不能让用户决定创建和不创建,应该由我们去控制
-
构造方法是用来创建对象的,不能让用户直接访问我们的构造方法
-
1 构造方法私有化
-
把构造方法私有化了,就意味着用户创建不了对象
-
对外提供一个公共的静态方法,调用该方法就能返回一个对象,
-
2 创建一个公共的静态的方法用来返回当前类的对象,并且 只实例化一次
-
当调用处通过该方法获取对象的时候,先判断是否已经创建了对象,如果没有就创建一个并存储
-
如果已经创建 就直接返回该对象
-
所以 需要 一个存储对象的变量,这个变量必须是和类生命周期相关的
-
如果是一个局部变量的话,方法每次调用,都会重新初始化局部变量,所以 每次都会创建对象
-
如果是个成员变量,那么问题更严重,静态方法中不能直接操作成员变量
-
所以 只能是静态变量,并且这个变量要私有化不能被外部访问,
-
3 创建一个私有化的静态变量,用于存储当前类的对象(变量的类型,是当前类类型)
- 根据对象不同的创建时机,分为两种情况
-
1 懒汉模式 : 第一次获取对象的时候,再创建对象
-
2 饿汉模式 : 加载类的时候,就创建对象
public class SglClient {
public static void main(String[] args) {
System.out.println(_01_Singleton.getInstance());
System.out.println(_01_Singleton.getInstance());
System.out.println(_01_Singleton.getInstance());
System.out.println(_01_Singleton.getInstance());
System.out.println("----------");
System.out.println(_02_Singleton.getInstance());
System.out.println(_02_Singleton.getInstance());
System.out.println(_02_Singleton.getInstance());
System.out.println(_02_Singleton.getInstance());
// TODO Auto-generated method stub
}
饿汉模式
package Singleleton;
// 饿汉模式 : 加载完之后 就立刻创建对象
public class _02_Singleton {
// 1 构造方法私有化
private _02_Singleton() {
}
// 静态变量在类加载阶段初始化,并且整个程序生命周期中只初始化一次
private static _02_Singleton s = new _02_Singleton();
// 返回该对象
public static _02_Singleton getInstance() {
return s;
}
}
懒汉模式
package Singleleton;
//懒汉模式 : 第一次获取对象的时候,再创建对象
public class _01_Singleton {
// 私有化构造方法
private _01_Singleton() {
}
// 私有化静态变量,用于存储当前对象
private static _01_Singleton s;
// 对外提供一个获取当前对象的方法
public static _01_Singleton getInstance() {
// 判断s是否为空,
// 如果为空 说明没有创建过对象,就创建一个
if (s == null) {
s = new _01_Singleton();
}
// 不为空就说明创建过对象,就直接返回该对象
return s;
}
}
三.工厂模式
工厂模式 : 把创建对象的语句单独封装成一个工厂模式
*
- 这样 所有用到这个对象的地方,都去工厂中获取,把类之间强依赖关系变弱,灵活度更高
public class _01_Factory {
public static void main(String[] args) {
fight(WeaponFactory.getWeapon());
fight(WeaponFactory.getWeapon());
fight(WeaponFactory.getWeapon());
fight(WeaponFactory.getWeapon());
fight(new AK47());
fight(new AK47());
}
public static void fight(Weapon w) {
w.fireInTheHole();
}
public interface Weapon {
public void fireInTheHole();
}
public class WeaponFactory {
public static Weapon getWeapon() {
// return new ZhuanTou();
return new RPG();
}
}
public class AK47 implements Weapon{
@Override
public void fireInTheHole() {
System.out.println("DADADADA~");
}
public class RPG implements Weapon{
@Override
public void fireInTheHole() {
System.out.println("peng~");
}