模式定义
享元模式(Flyweight Pattern):运用共享技术有效地支持大量细颗粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。享元模式是一种对象结构型模式。
模式结构
Flyweight
抽象享元类声明一个接口,通过它可以接受并作用于外部状态。在抽象享元类中定义了具体享元类公共的方法,这些方法可以向外界提供享元的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。ConcreteFlyweight
具体享元类实现了抽象享元接口,其实例称为享元对象,在具体享元类中为内部状态提供了存储空间,由于具体享元对象必须是可以共享的,因此它所存储的状态必须是内部的,即它独立存在于自己的环境中。可以结合单例模式来实际具体享元类,为每一个具体享元类提供唯一的享元对象。UnSharedConcreteFlyweight
并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类则设计为非共享具有享元类,当需要一个非共享具体享元类的对象时可以直接通过实例化创建;在某些享元模式的层次结构中,非共享具体享元对象还可以将具体享元对象作为子节点。FlyweightFactory
享元工厂类用于创建并管理享元对象;它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储键值对的集合,可以结合工厂模式进行设计;当用户请求一个具体享元对象时,享元工厂提供存储在享元池中已创建的实例或者创建一个新的实例,返回该新建实例并将其存储在享元池中。
享元模式以共享的方式高效地支持大量的细颗粒度对象,享元对象能做到共享的关键是区分内部状态和外部状态。享元模式的核心在于享元工厂类。
实例——无外部状态
很多网络设备都是支持共享的,如交换机、集线器等,多台计算机终端可以连接同一台网络设备,并通过该设备进行数据转发,现用享元模式模拟共享网络设备的设计原理。
实例类图如下所示:
public interface NetworkDevice {
public String getType();
public void use();
}
public class Switch implements NetworkDevice {
private String type;
public Switch(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void use() {
System.out.println("Linked by switch, type is " + this.type);
}
}
public class Hub implements NetworkDevice {
private String type;
public Switch(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void use() {
System.out.println("Linked by Hub, type is " + this.type);
}
}
public class DeviceFactory {
private ArrayList devices = new ArrayList();
private int totalTerminal = 0;
public DeviceFactory() {
NetworkDevice nd1 = new Switch("Cisco-WS-C2950-24");
devices.add(nd1);
NetworkDevice nd2 = new Hub("TP-LINK-HF8M");
devices.add(nd2);
}
public NetworkDevice getNetworkDevice(String type) {
if (type.equalsIgnoreCase("cisco")) {
totalTerminal++;
return (NetworkDevice)devices.get(0);
}
else if (type.equalsIgnoreCase("tp") {
totalTerminal++;
return (NetworkDevice)devices.get(1);
}
else {
return null;
}
}
public int getTotalDevice() {
return devices.size();
}
public int getTotalTerminal() {
return totalTerminal;
}
}
实例——有外部状态
虽然网络设备可以共享,但是分配给每一个终端计算机的端口是不同的,因此多台计算机虽然可以共享同一个网络设备,但必须使用不同的端口。可以将端口从网络设备中抽取出来作为外部状态,需要时再进行设置。
实例类图如下所示:
public interface NetworkDevice {
public String getType();
public void use(Port port);
}
public class Switch implements NetworkDevice {
private String type;
public Switch(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void use(Port port) {
System.out.println("Linked by switch, type is " + this.type + "Port is " +
port.getPort());
}
}
public class Hub implements NetworkDevice {
private String type;
public Switch(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void use(Port port) {
System.out.println("Linked by Hub, type is " + this.type + "Port is " +
port.getPort());
}
}
public class DeviceFactory {
private ArrayList devices = new ArrayList();
private int totalTerminal = 0;
public DeviceFactory() {
NetworkDevice nd1 = new Switch("Cisco-WS-C2950-24");
devices.add(nd1);
NetworkDevice nd2 = new Hub("TP-LINK-HF8M");
devices.add(nd2);
}
public NetworkDevice getNetworkDevice(String type) {
if (type.equalsIgnoreCase("cisco")) {
totalTerminal++;
return (NetworkDevice)devices.get(0);
}
else if (type.equalsIgnoreCase("tp") {
totalTerminal++;
return (NetworkDevice)devices.get(1);
}
else {
return null;
}
}
public int getTotalDevice() {
return devices.size();
}
public int getTotalTerminal() {
return totalTerminal;
}
}