装饰器的作用就是动态扩展某一个类的功能
/**
- 装饰器模式
- 1)不使用继承
- 2)不改变原类的文件
- 3)动态扩展
- Component: InputStream
- 统一接口,装饰类/被装饰类的基本接口
- ConcreteComponent FileInputStream
- 具体实现类(被装饰类),它本身是一个比较完整的类
- Decorator: FilterInputStream
- 装饰类,实现Component接口同时还会在内部维护一个ConcreateComponent的实例,并且
- 这个实例是在构造函数中初始化
- ConcreteDecorator BufferInputStream
- 具体的装饰类,每一种装饰产品都有不同的装饰效果
- 组合 利用已存在类的功能,在新类中创建一个原有类的实例
-
显示的
- 继承 描述一种"是"的关系 利用已存在类的功能,新类继承原有类
-
当父类被修改,会影响到所有继承它的子类,增加维护难度和成本
-
隐式的
- 例:Transport Car Bus Tyre
- Car Bus is Transport 继承
- Car has mang Tyres/ Bus has many Tyres 组合
*/
装饰类的一个简单实现,用于理解
Component :被装饰类接口
ConcreteComponent :具体实现类(被装饰类)
Decorator:装饰类(可以理解为经纪人)
ConcreteDecorator:具体实现类(演员本人)
interface Component{
void method();
}
/**
* 被装饰类
*/
class ConcreteComponent implements Component{
@Override
public void method() {
System.out.println("concreteComponent method");
}
}
/**
* 装饰类 实现Component接口
*/
abstract class Decorator implements Component{
//内部会维护一个ConcreateComponent的实例
private Component component;
//这个实例是在构造函数中初始化
public Decorator(Component component){
this.component = component;
}
@Override
public void method() {
component.method();
}
}
/**
* 具体装饰类A类
*/
class ConcreteDecoratorA extends Decorator{
public ConcreteDecoratorA(Component component) {
super(component);
}
public void methodA1(){
System.out.println("装饰器A所实现的功能1");
}
public void methodA2(){
System.out.println("装饰器A所实现的功能2");
}
}
/**
* 具体装饰类B类
*/
class ConcreteDecoratorB extends Decorator{
public ConcreteDecoratorB(Component component) {
super(component);
}
public void methodB1(){
System.out.println("装饰器B所实现的功能1");
}
public void methodB2(){
System.out.println("装饰器B所实现的功能2");
}
}
public class TestDemo6 {
public static void main(String[] args) {
//被装饰的对象
Component component = new ConcreteComponent();
//被装饰的对象本身具有的功能
component.method();
//装饰成A
ConcreteDecoratorA a = new ConcreteDecoratorA(component);
a.method();
a.methodA1();
a.methodA2();
//装饰成B
ConcreteDecoratorB b = new ConcreteDecoratorB(component);
b.method();
b.methodB1();
b.methodB2();
}
}
序列化和反序列化
/**
- Java中序列化与反序列化
- 类中的对象会随这程序的终止被垃圾回收器而销毁,如果在不想要创建对象的情况下
- 调用该类中的功能,考虑使用序列化将原有的对象转换为字节流存到磁盘上
- 对象的序列化:对象-》字节流 永久保存至磁盘文件或者网络传送
- 对象的反序列化:字节流-》对象
- 一个凭他上序列化的对象在不同平台都可以被反序列化
- 面试题:序列化机制存在的意义?
- 对象的序列化机制允许将Java对象转换为字节流,这些字节流可以永久地保存在磁盘
- 上,或者咋网络中传输,从一个网络节点到另外一个网络节点,可以使得某一个对象
- 脱离原有的程序能够对立存在,其他程序一旦获取到当前的字节流,都可以将这种字节
- 流恢复为原有的对象。
- 如何实现对象的序列化:
- 1)对象所在类实现Serializable接口,使用Serializable接口实现序列化
-
- 创建ObjectOutputStream,这个输出流是一个处理流,所以必须建立在其他
- 节点流的基础上
- 3)调用ObjectOutputStream对象的writeObject去序列化对象
- 如何实现对象的额反序列化:
- 1)创建ObjectInputStream,这个输入流是一个处理流,所以必须建立在其他
- 节点流的基础上
- 2)调用ObjectInputStream对象readObject方法读取流中对象
- 注意:
- 1)反序列读取到的只是Java对象,提供当前对象所属的类
- 2)Person只有一个构造器,同时反序列化时没有打印当前构造器中的内容,那就
- 说明这里并没有初始化对象
- 3)当一个序列化的类如果有多个父类的,这些父类要么提供一个无参构造器,要么
- 就也得实现序列化接口,如果以上都没有则表示父类是不可被序列化的
- 什么是serialVersionUID?
- 如果某个对象保存在磁盘上,那么序列化的时候就会根据该对象的哈希码生成serialVersionUID
- 标记在当前的对象上,用于对象的版本控制。当修改原有的类,反序列化时没有办法将原有的对象
- 恢复,因为serialVersionUID已经为新类重新生成
- ArrayList中的序列化和反序列化
- ArrayList重写了writeObject和readObejct方法控制序列化过程
- 注意:tranisent关键字修饰的属性不参与序列化与反序列化的过程
- 当一个变量前加上这个关键字,在序列化的规程中该变量不会写入,而
- 反序列化之后该变量会是对应类型的初始值
- 调用到ArrayList中writeObject的过程?
- ObjectOutPutStream.writeObject
- ->writeObject0
- ->writeOrdinaryObject
- ->writeSerialData
- ->invokeWriteObject 反射机制
*/
package io;
import java.io.*;
import java.util.ArrayList;
```java
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
System.out.println("实例化Person对象");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class TestDemo7 {
public static void main(String[] args){
ArrayList<String> stringList = new ArrayList<>();
stringList.add("hello");
stringList.add("world");
stringList.add("hello");
stringList.add("tulun");
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
//序列化
oos = new ObjectOutputStream(new FileOutputStream("stringList.txt"));
oos.writeObject(stringList);
//反序列化
ois = new ObjectInputStream(new FileInputStream("stringList.txt"));
ArrayList<String> newStringList = (ArrayList)ois.readObject();
System.out.println(newStringList);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
oos.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//序列化一个Person对象
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
//创建一个ObjectOutputStream
oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
//创建一个ObjectInputStream
ois = new ObjectInputStream(new FileInputStream("a.txt"));
//调用writeObject实现序列化
Person person = new Person("tulun", 18);
oos.writeObject(person);
//通过readObect实现反序列化
Person p = (Person)ois.readObject();
System.out.println(p.getName()+": "+p.getAge());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
oos.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}