设计模式之享元模式

        如果一个程序需要使用大量对象,但这些对象中有好多重复的对象,如果对其进行重复的创建对象,那么必然会造成很大的开销,其中这里面有很大一部分开销是不必要的。我们之前讲单例模式的时候,讲过单例模式就是严格控制单个进程只有一个实例对象,而且对于该实例对象不重复创建,这样可以节省系统开销。其实,本文提到的享元模式也是使用同样的思想,使得创建过对象不再重复创建,并且在使用过程中创建有需要的对象,如果对象已经创建过只需要直接取出,如果没有则进行创建并存储。说到底享元模式其实更像一个创建单例的简单工厂。

1.适用性和优缺点
1.适用性
当具备下列情况时,使用享元模式:
a.一个应用程序使用了大量的对象。
b.完全由于使用了大量的对象,造成很大的存储开销。
c.对象的大多数状态都可变为外部状态。
d.如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
e.应用程序不依赖于对象标识。由于享元对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。
f.当一个类有许多的实例,而这些实例能被同一个方法控制的时候。
g.ThreadPool、线程池和数据库连接池都有使用享元模式。

2.优点
a.减少运行时对象实例的个数,节省内存。
b.将许多“虚拟对象”的状态集中管理。

3.缺点
一旦实现了它,那么单个的逻辑实例将无法拥有独立而不同的行为。

2.示例讲解
                          
Flyweight:描述一个接口,通过这个接口flyweight可以接受并作用于外部状态。
FlyweightImpl:实现Flyweight接口,并为内部状态(如果有的话)增加存储空间。FlyweightImpl对象必须是共享的。
FlyweightFactory:创建并管理flyweight对象。确保合理地共享flyweight。当用户请求一个flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。类似一个受单例模式约束的简单工厂。
首先建立一个享元接口,有一个内部函数可以接受外部状态。
package flyweightpattern;

public interface Flyweight {

    void action(int arg);
}
一个享元实现类,实现方法
package flyweightpattern;

public class FlyweightImpl implements Flyweight {
	String msg;
	public FlyweightImpl(String msg)
	{
		this.msg=msg;
	}
    public void action(int arg) {
        // TODO Auto-generated method stub
        System.out.println(msg+"的参数值: " + arg);
    }
}
        然后是享元工厂,负责创建享元对象和管理享元对象,其中flyweights是一个Map集合,getFlyweight方法是一个工厂方法,如果在flyweights找到对象,则不再创建,直接从集合中取出即可,如果没有目标对象,则进行创建享元对象并存储。其中getFlyweight对象传入的参数,是flyweights集合的key值,也是创建享元对象的参数,也比较容易区分对象是否相同。
package flyweightpattern;
import java.util.*;
public class FlyweightFactory {

    private static Map<String,Flyweight> flyweights = new HashMap();
    
    public FlyweightFactory(String arg) {
        flyweights.put(arg, new FlyweightImpl(arg));
    }
    
    public static Flyweight getFlyweight(String key) {
        if (flyweights.get(key) == null) {
            flyweights.put(key, new FlyweightImpl(key));
        }
        return flyweights.get(key);
    }
    
    public static int getSize() {
        return flyweights.size();
    }
}
        测试程序,
package flyweightpattern;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Flyweight fly1 = FlyweightFactory.getFlyweight("a");
        fly1.action(1);
        
        Flyweight fly2 = FlyweightFactory.getFlyweight("a");
        System.out.println(fly1 == fly2);
        
        Flyweight fly3 = FlyweightFactory.getFlyweight("b");
        fly3.action(2);
        
        Flyweight fly4 = FlyweightFactory.getFlyweight("c");
        fly4.action(3);
        
        Flyweight fly5 = FlyweightFactory.getFlyweight("d");
        fly4.action(4);
        fly5.action(5);
        System.out.println(FlyweightFactory.getSize());
    }
}
        运行结果:
a的参数值: 1
true
b的参数值: 2
c的参数值: 3
c的参数值: 4
d的参数值: 5
4
        根据上述例子可以更加清楚地看出,享元模式类似于一个要求更加严格的简单工厂模式,要求它的工厂方法符合单例的要求,即创建过的对象不再重复创建。


3.与其它模式的比较
1.享元模式与单例模式
单例模式是严格控制单个进程中只有一个实例对象,是自身控制,需要增加不属于该对象本身的逻辑。而享元模式可以通过自己实现对外部的单例,也可以在需要的时候使用创建更加的对象,享元模式的逻辑判断都交给工厂类进行判断。

2.享元模式与简单工厂模式
简单工厂模式只负责创建对象,而享元模式还包含对对象的存储和管理。







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值