设计模式之原型模式和享元模式

本文会介绍一下原型模式和享元模式
放在一起介绍是觉得它们有一点相似之处

思想

原型模式:提供对象的一个拷贝,也就是clone。有深克隆和浅克隆两种。
设计模式之原型模式和享元模式_第1张图片

享元模式:在享元工厂类存储着享元类的多个对象,每次使用享元类的对象时,返回享元工厂类中的一个结果即可。
设计模式之原型模式和享元模式_第2张图片

定义

1)原型模式
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

2)享元模式
运用共享技术有效的支持大量细粒度对象的复用。

原型模式浅克隆、深克隆

通过clone()出来的两个对象是不在同一块地址空间的,
B = A.clone();
B == A is false

1)浅克隆
在浅克隆中,被复制对象的所有普通成员变量都具有与原来的对象相同的值,而所有的对其它对象的引用仍然指向原来的对象。

如果复制出来一个新对象,那么新对象跟旧对象里面的引用对象是指向用一片地址空间的。
设计模式之原型模式和享元模式_第3张图片
2)深克隆
深克隆把要复制的对象中所引用的对象都复制了一遍,新对象跟旧对象里面的引用成员变量是指向不同的堆的

设计模式之原型模式和享元模式_第4张图片

原型模式实际问题

由于邮件对象包含的内容较多,某系统中需要提供一个邮件复制功能,对于已经复制好的邮件对象,可以通过复制的方法创建一个新的邮件对象,如果需要改变某部分内容,只需要修改复制后的对象。

现用浅克隆实现复制邮件(E-mail)的同时不复制附件(Attachment)
用深克隆实现复制邮件(E-mail)的同时复制附件(Attachment)

类图、模式结构和Demo

  1. Prototype(抽象原型类):下面类图未设计
  2. ConcretePrototype(具体原型类):Email(浅克隆)、EmailDeep(深克隆)

1)浅克隆
设计模式之原型模式和享元模式_第5张图片
注意:原型类需实现Cloneable接口

public class EmailTint implements Cloneable{
     
    private Attachment attachment;

    public EmailTint() {
     
        this.attachment = new Attachment();
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
     
        return super.clone();
    }
    public Attachment getAttachment() {
     
        return this.attachment;
    }
    public void display() {
     
        System.out.println("查看邮件");
    }
}
//作为邮件类里面的引用对象
public class Attachment {
     
    public void download() {
     
        System.out.println("下载附件...");
    }
}
public class PrototypeDemo {
     
    public static void main(String[] args) throws CloneNotSupportedException {
     
        EmailTint emailTint, copyEmailTint;
        emailTint = new EmailTint();
        copyEmailTint = (EmailTint) emailTint.clone();
        System.out.println(emailTint);//在不同的地址空间
        System.out.println(copyEmailTint);//在不同的地址空间
        System.out.print("emailTint == copyEmailTint : ");
        System.out.println(emailTint == copyEmailTint);//false
        System.out.print("emailTint.getAttachment() == copyEmailTint.getAttachment() : ");
        System.out.println(emailTint.getAttachment() == copyEmailTint.getAttachment());//true
    }
}

设计模式之原型模式和享元模式_第6张图片

2)深克隆
深克隆借助序列化操作,将对象写入流中再读出
设计模式之原型模式和享元模式_第7张图片
注意:此时原型类跟原型类里面的引用对象类都要实现Serializable接口。
为了区分两个模式,深克隆调用的是deepClone,也可以同时实现Serializable、Cloneable,并实现clone方法

public class EmailDeep implements Serializable {
     
    private Attachment attachment;

    public EmailDeep() {
     
        this.attachment = new Attachment();
    }

    public Object deepClone() throws CloneNotSupportedException, IOException, ClassNotFoundException {
     
        //将对象写入流中
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
        //将对象从流中取出
        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        Object o = ois.readObject();
        return o;
    }
    public Attachment getAttachment() {
     
        return this.attachment;
    }
    public void display() {
     
        System.out.println("查看邮件");
    }
}
public class Attachment implements Serializable {
     
    public void download() {
     
        System.out.println("下载附件...");
    }
}
public class PrototypeDemo {
     
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
     
        EmailDeep emailDeep, emailDeepCopy;
        emailDeep = new EmailDeep();
        emailDeepCopy = (EmailDeep) emailDeep.deepClone();
        System.out.print("emailDeep == emailDeepCopy : ");
        System.out.println(emailDeep == emailDeepCopy);//false

        System.out.print("emailDeep.getAttachment() == emailDeepCopy.getAttachment() : ");
        System.out.println(emailDeep.getAttachment() == emailDeepCopy.getAttachment());//false
    }
}

设计模式之原型模式和享元模式_第8张图片

享元模式实际问题

很多网络设备都支持共享,多台计算机终端可以连接同一台网络设备,并通过该设备进行网络通信。使用享元模式对该网络设备进行共享。

类图、模式结构和Demo

  • Flyweight(抽象享元类):NetWorkDevice
  • ConcreteFlyweight(具体享元类):Switch、Hub
  • UnSharedConcreteFlyweight(非共享具体享元类)
  • FlyweightFactory(享元工厂):提供一个存储对象的享元池,DeviceFactory

类图:
设计模式之原型模式和享元模式_第9张图片
demo:

interface NetworkDevice {
     
    String getType();
    void use();
}
public class Switch implements NetworkDevice{
     
    private String type;

    public Switch(String type) {
     
        this.type = type;
    }
    @Override
    public String getType() {
     
        return this.type;
    }

    @Override
    public void use() {
     
        System.out.println("使用" + this.type + "~");
    }
}
public class Hub implements NetworkDevice{
     
    private String type;
    public Hub(String type) {
     
        this.type = type;
    }
    @Override
    public String getType() {
     
        return this.type;
    }

    @Override
    public void use() {
     
        System.out.println("使用" + this.type + "~");
    }
}
public class DeviceFactory {
     
    //享元池
    private ArrayList<NetworkDevice> devices = new ArrayList<>();
    private int totalTerminal = 0;
    public DeviceFactory() {
     
        //享元对象,随着系统的启动只有这两个
        devices.add(new Switch("Cisco-WS-C2904-24"));
        devices.add(new Hub("TP-LINK-F848"));
    }
    public NetworkDevice getDeviceFactory(String type) {
     
        if (type.equalsIgnoreCase("cisco")) {
     
            ++totalTerminal;
            //返回其中一个享元对象
            return devices.get(0);
        } else if (type.equalsIgnoreCase("tp")) {
     
            ++totalTerminal;
            //返回另一个
            return devices.get(1);
        } else {
     
            System.out.println("不匹配!");
            return null;
        }
    }

    public int getTotalTerminal() {
     
        return totalTerminal;
    }

    public int getDevices() {
     
        return devices.size();
    }

    @Override
    public String toString() {
     
        StringBuilder sbr = new StringBuilder();
        for (NetworkDevice device : devices){
     
            sbr.append(device.getType()).append("\n");
        }
        return sbr.toString().trim();
    }
}
public class FlyweightDemo {
     
    public static void main(String[] args) {
     
        NetworkDevice nd1, nd2, nd3, nd4, nd5;
        DeviceFactory deviceFactory = new DeviceFactory();
        System.out.println("======================");
        nd1 = deviceFactory.getDeviceFactory("cisco");
        System.out.println(nd1.getType());
        nd1.use();
        System.out.println("======================");
        nd2 = deviceFactory.getDeviceFactory("cisco");
        System.out.println(nd2.getType());
        nd2.use();
        System.out.println("======================");
        nd3 = deviceFactory.getDeviceFactory("tp");
        System.out.println(nd3.getType());
        nd3.use();
        System.out.println("======================");
        nd4 = deviceFactory.getDeviceFactory("cisco");
        System.out.println(nd4.getType());
        nd4.use();
        System.out.println("======================");
        nd5 = deviceFactory.getDeviceFactory("tp");
        System.out.println(nd5.getType());
        nd5.use();
        System.out.println("======================");
        System.out.println("提供对象数目:"+deviceFactory.getTotalTerminal());
        System.out.println("已有对象种类:"+deviceFactory.getDevices());
        System.out.println(deviceFactory);
        System.out.println("======================");
    }
}

设计模式之原型模式和享元模式_第10张图片

你可能感兴趣的:(设计模式)