设计模式(十二)----享元模式

概述

面向对象可很好地解决一些灵活性或扩展性的问题,但若系统中的对象数量过多就会对系统性能产生影响。
享元模式提供了一种解决方案,使用共享技术实现相同或相似对象的重用。
享元模式(Flyweight Pattern)主要用于减少对象的创建数量,该设计模式属于结构型模式。享元模式就是运用共享技术,有效地支持大量细粒度对象的复用。系统使用少量对象,而且这些对象都比较相似,状态变化小,可实现对象的多次复用。
内部状态:在享元模式中可以共享的相同内容。
外部状态:需外部环境来设置,不能共享的状态。
享元模式的本质是分离与共享,分离变与不变,并且共享不变。
实际使用中,能够共享的内部状态是有限的,所以享元模式一般都设计为较小的对象,它所包含的内部状态较少。
可通过设置不同的外部状态来使得相同的对象具备一些不同的特性,而内部状态设置为相同的部分。
内部状态存储于享元对象内部,而外部状态应由客户端考虑。
享元模式存在如下几个角色:
Flyweight:抽象享元类。所有具体享元类的超类或接口。
ConcreteFlyweight:具体享元类。指定内部状态,为内部状态增加存储空间。
UnsharedConcreteFlyweight:非共享具体享元类。指出那些不需要共享的Flyweight子类。
FlyweightFactory:享元工厂类。用来创建并管理Flyweight对象,主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或新建一个(若不存在时)。
享元模式的核心在于享元工厂类,该类提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中取,若享元池中不存在,则创建一个新的享元对象返回给用户,并在该享元池中保存该新增对象。

实例

假如有个绘图应用程序,通过它可绘制各种形状、颜色的图形,这里的形状和颜色就是内部状态,通过享元模式可实现该属性的共享。
抽象类Shape

public abstract class Shape {
	public abstract void draw();
}

具体类Circle

public class Circle extends Shape {
	private String color;
	public Circle(String color) {
		this.color = color;
	}
	public void draw() {
		System.out.println(color + "圆形");
	}
}

享元工厂类ShapeFactory

public class ShapeFactory {
	private static final Map<String,Shape> shapeMap = new HashMap<String,Shape>();
	public static Shape getShape(String color) {
		Circle circle = (Circle)shapeMap.get(color);
		if(circle == null) {
			circle = new Circle(color);
			shapeMap.put(color,circle);
		}
		return circle;
	}
	//获取集合中对象个数
	public static int getNum() {
		return shapeMap.size();
	}
}

客户端程序FlyweightPatternDemo

public class FlyweightPatternDemo {
	public static void main(String[] args) {
		Shape shape1 = ShapeFactory.getShape("黑色");
		shape1.draw();

		Shape shape2 = ShapeFactory.getShape("白色");
		shape2.draw();

		Shape shape3 = ShapeFactory.getShape("红色");
		shape3.draw();

		Shape shape4 = ShapeFactory.getShape("黑色");
		shape4.draw();

		Shape shape5 = ShapeFactory.getShape("红色");
		shape5.draw();

		System.out.println("共绘制" + ShapeFactory.getNum() + "种颜色的图形");
	}
}

打印结果
在这里插入图片描述

总结

优点:极大减少系统中对象个数,由于使用了外部状态,外部状态相对独立,不会影响到内部状态,所以享元模式使得享元对象能够在不同的环境下被共享。
缺点:需区分内部状态和外部状态,使得应用程序在某种程度上来说复杂化了;为使对象可共享,需将享元对象的状态外部化,读取外部状态使得运行时间变长。
使用场景:一个系统中存在大量相同或相似的对象,对象的大部分状态都可外部化,可将这些外部状态传入对象中。
享元模式核心在于享元工厂,它用来确保合理地共享享元对象。内部状态为不变共享部分,外部状态是可变部分,应当由客户端负责。
享元模式在编辑软件中有大量应用,如在一个文档中多次出现相同的图片,则只需创建一个图片对象,通过在应用程序中设置该图片出现的位置,可实现该图片在不同地方多次重复显示。
在JDK类库中定义的String类也是使用享元模式的典型,若有则返回,若没有则创建一个字符串保存在字符串缓存池里。
主要解决:当有大量对象时,可能造成内存溢出,可将相同的公共部分抽离出来,若有相同的业务请求,直接返回在内存中已有的对象,避免重复创建。
注:注意划分外部状态和内部状态,否则可能会出现线程安全的问题,这些类须有一个工厂对象加以控制。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值