`
wangchao_17915566
  • 浏览: 167842 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

了解享元模式

阅读更多

      享元模式,高效的支持细粒度的对象。享元对象能做到共享的关键是区分内蕴状态和外蕴状态,一个内蕴状态是存储在享元对象内部的,并不会随环境的变化而变化,因此,一个享元可以具有内蕴状态并可以共享。一个外蕴状态是随环境变化而变化的,不可以共享。享元对象的外蕴状态必须由客户端保存,并在享元对象后被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不能影响内蕴状态,即相互独立。

      上面说了一大堆非常抽象,用gof的例子来说,例如一个文本编辑器,在上面可以编辑字母,共有52个字母,含大小写,如果它要写1000字母的文章,则有接近20倍的字母都会重复,即没写一个字母,会实例化一次字母的父类。这样就会花费很多资源,并且每一个字母都有可能带不同的样式。从这分析,我们就可以使用享元模式。首先字母就可以作为内蕴状态,因为他们是固定的52个,并且如果再次使用重复字母,我们就可以通过共享来实现,而字母的样式我们就认为它是外蕴状态,是可以随之改变的。

      接下来,看看代码。

      定义接口,并创建一个改变字体样式方法

public interface Flyweight {
    public void operation(String state);
}

    实现此接口

public class ConcerteFlyweight implements Flyweight{
	//内蕴状态
	private Character intrinsicState = null;
	//传进来的参数属于外晕状态
	public ConcerteFlyweight(Character state) {
		this.intrinsicState = state;
	}

	public void operation(String state) {
		System.out.println("intrinsicState="+intrinsicState+",Extrinsic State="+state);
	}

}

内蕴状态也可认为是类内部变量,而外蕴状态则是从外部传入的参数。

接下来定义一个工厂类,因为客户端不能直接将具体的享元类实例化,而必须通过一个工厂对象,利用一个factory()得到享元对象。当客户端需要单纯的享元对象的时候,需要调用享元工厂factory()方法,并传入所需的内蕴状态,由工厂方法得到所需的享元对象。

public class FlyweightFactory {
	
	private HashMap flies = new HashMap();
	private Flyweight fly;
	
	public FlyweightFactory(){
		
	}
	
	//字体样式
	public Flyweight factory(Character state){
		if(flies.containsKey(state)){
			return (Flyweight)flies.get(state);
		}else{
			fly = new ConcerteFlyweight(state);
			flies.put(state, fly);
			return fly;
		}
	}
}

 

接下来,进行测试下

public class Client {
	
	public static void main(String[] args){
		FlyweightFactory factory=new FlyweightFactory();
		Flyweight fly=factory.factory(new Character('a'));
		fly.operation("罗马字符");
		fly.operation("新罗马字符");
		fly=factory.factory(new Character('b'));
		fly.operation("阿拉伯字符");
	}
}

 

测试结果:

intrinsicState=a,Extrinsic State=罗马字符
intrinsicState=a,Extrinsic State=新罗马字符
intrinsicState=b,Extrinsic State=阿拉伯字符

 

可以看到字母a共享了一次,即内蕴,字体样式不断改变,即外蕴。

 

以上是单纯享元,下面看看什么是复合享元。

依然是上面的例子,如果在编辑某段字母是都是同一个样式,这就可以使用复合享元。

还是同样的接口,同样的实现类

public interface Flyweight {
public void operation(String state);
}


public class ConcreteFlyweight implements Flyweight
	{
	  private Character intrinsicState=null;
	  //构造子,内蕴状态作为参数传入
	  public ConcreteFlyweight(Character state)
	  {
	    this.intrinsicState=state;
	  }
	  //外蕴状态作为参数传入方法
	  public void operation(String state)
	  {
	    System.out.println("Intrinsic state="+intrinsicState+",Extrinsic State="+state);
	  }
	}

 

不同的是,复合享元由单纯享元对象通过复合而成,因此提供了add()这样的聚合管理方法,由于复合享元对象具有不同的聚集元素,这些聚集元素在复合后被创建之后加入,所以这些复合享元对象是不可改变的。复合享元实现接口,并实现operation方法,这个参数对复合享元来说就是外蕴。一个复合享元对象的所有单纯享元对象元素的外蕴状态都是与复合享元对象的外蕴状态相等的,而对象所含有的单纯享元对象的内蕴状态一般不想等。

      就编辑器来说,我某一段输入abac,并且都是新罗马字符,从这里理解上面的语句,就是新罗马字符即复合享元的外蕴,与每一个字母的单纯享元的外蕴是一样的,因为他们的样式都是"新罗马".而内蕴却不一定相同,因为,a,b,c是完全不同的字母。这样就理解了。

下面接着看代码:

public class ConcreteCompositeFlyweight implements Flyweight{
	
	  private HashMap flies=new HashMap(10);
	  private Flyweight flyweight;
	  public ConcreteCompositeFlyweight() {  }
	  //增加一个新的单纯享元对象到聚集中
	  public void add(Character key,Flyweight fly)
	  {
	    flies.put(key,fly);
	  }
	  //外蕴状态作为参数传入到方法中
	  public void operation(String extrinsicState)
	  {
	    Flyweight fly=null;
	    for(Iterator it=flies.entrySet().iterator();it.hasNext();)
	    {
	      Map.Entry e=(Map.Entry)it.next();
	      fly=(Flyweight)e.getValue();
	      fly.operation(extrinsicState);
	    }
	  }
	}

 

接下来看看工厂类,跟单纯享元一样,客户端不能直接调用享元对象,只能通过工厂类。

public class FlyweightFactory
{
  private HashMap flies=new HashMap();
  
  public FlyweightFactory() {  }
  
  //单纯享元工厂方法,所需状态以参量形式传入
  public Flyweight factory(Character state)  
  {
    if(flies.containsKey(state))
    {
      return (Flyweight)flies.get(state);
    } else {
      Flyweight fly=new ConcreteFlyweight(state);
      flies.put(state,fly);
      return fly;
    }
  }
  
  //符合享元工厂方法,所需状态以参量形式传入,这个参量巧好可以使用string类型
  public Flyweight factory(String compositeState)
  {
    ConcreteCompositeFlyweight compositeFly=new ConcreteCompositeFlyweight();
    int length=compositeState.length();
    Character state=null;
    for(int i=0;i<length;i++)
    {
      state=new Character(compositeState.charAt(i));
      System.out.println("factory("+state+")");
      compositeFly.add(state,this.factory(state));
    }
    return compositeFly;
  }
  
}

 

这里就是将复合享元对象,分解成若干个单纯享元对象,进行处理。

最后我们测试一下

public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		FlyweightFactory factory=new FlyweightFactory();
		Flyweight fly=(Flyweight) factory.factory("abac");
		fly.operation("罗马字符");
	}

}

 

测试结果:

factory(a)
factory(b)
factory(a)
factory(c)
Intrinsic state=a,Extrinsic State=罗马字符
Intrinsic state=c,Extrinsic State=罗马字符
Intrinsic state=b,Extrinsic State=罗马字符

 

这就说明了,将复合享元对象差分为若干个单纯享元对象处理,并且外蕴是相同的。

分享到:
评论

相关推荐

    浅谈JAVA设计模式之享元模式

    主要介绍了JAVA设计模式之享元模式的的相关资料,文中详细的介绍了享元模式的概念以及使用方法,感兴趣的朋友可以了解下

    [源代码] 《易学 设计模式》 随书源代码

    第15章 源源不断:享元模式 (Flyweight) 第16章 按部就班:模板方法模式 (TemplateMethod) 第17章 风吹草动:观察者模式 (Observer) 第18章 变化多端:状态模式 (State) 第19章 明修栈道,暗度陈仓:策略模式 ...

    精通python设计模式与源码

    本书用实际生活中的例子带你了解...第二部分介绍处理一个系统中不同实体(类、对象等)之间关系的设计模式,包括外观模式、享元模式等;第三部分介绍处理系统实体之间通信的设计模式,包括责任链模式、观察者模式等。

    Mybatis 框架源码10种设计模式分析.pdf

    文章接着介绍了 Mybatis 框架源码中的 10 种设计模式应用,包括工厂模式、单例模式、原型模式、建造者模式、代理模式、适配器模式、桥模式、组合模式、享元模式和解释器模式。这些设计模式的应用能够帮助读者更好地...

    Java设计模式面试题汇总

    包括适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式、代理模式等。 行为型模式:通过类之间不同通信方式实现不同行为。包括责任链模式、命名模式、解释器模式、迭代器模式、中介者...

    软件设计模式知识点

    6. 享元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。 7. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 行为型模式 行为型模式主要用于描述对类或对象怎样交互和怎样分配...

    GoF 的 23 种设计模式

    享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。 模板方法(TemplateMethod)模式:...

    Java23种设计模式6大原则总结.doc

    常见的结构型模式有代理模式、装饰模式、适配器模式、组合模式、桥梁模式、外观模式、享元模式等。 行为型模式的主要功能是描述类或对象之间的交互和协作。常见的行为型模式有模板方法模式、命令模式、责任链模式、...

    Java Bug模式详解

    6.1 了解bug模式的重要性 6.2 选择bug模式的原因 6.3 如何组织bug模式 6.4 Bug诊断的快速参考 第7章 Rogue Tile模式 7.1 Rogue Tile bug模式简述 7.1.1 症状 7.1.2 起因、解决方法 和预防措施 7.2 提取代码...

    Java设计模式-图解--附代码

    有感于设计模式在日常开发中的重要性,同时笔者也自觉对设计模式小有心 得,故笔者*写二十三种设计模式的简单例子、 ...所附的例子非常简单,慢慢的引导读者从浅到深了解设计模式,并能从中享 受设计的乐趣。

    Java《易学设计模式》随书源码.rar

    Java《易学设计模式》随书源代码,书中介绍了多种JAva模式的方法和使用,比如简单工厂模式、工厂方法模式例子、状态模式例子、迭代器模式、解释器模式、命令模式、模板方法模式、享元模式、桥模式、代理模式、适配器...

    Java的23种设计模式疯狂Java总结.doc

    设计模式3 1.1 创立型模式4 1.1.1 工厂方法4 1.1.2 抽象工厂6 1.1.3 建造...享元模式32 1.2.7 代理模式34 1.3 行为型模式37 1.3.1 责任链模式37 1.3.2 命令模式40 1.3.3 解释器模式43 1.3.4 迭代器模式45 1.3.5 中介者...

    Java23种设计模式

    本份帮助文档主要是为了向读者介绍二十三种设计模式,包括模式的描述, 适用性,模*的组成部分,并附带有简单的例 ...所附的例子非常简单,慢慢的引导读者从浅到深了解设计模式,并能从中享 受设计的乐趣。

    二十三种设计模式【PDF版】

    设计模式之 Flyweight(共享元) 提供 Java运行性能,降低小而大量重复的类的开销. C. 行为模式 设计模式之 Command(命令) 什么是将行为封装,Command 是最好的说明. 设计模式之 Observer(观察者) 介绍如何使用 ...

    《现代通信网》实验三-交换机的基本操作.pptx

    《现代通信网》实验三-交换机的基本操作 ...本文档详细介绍了交换机的基本操作,包括交换机的类型、以太网交换机的基本配置、命令模式、在线帮助和命令缩写等方面的知识点,为读者提供了系统的了解交换机的知识基础。

    asp.net知识库

    2分法-通用存储过程分页(top max模式)版本(性能相对之前的not in版本极大提高) 分页存储过程:排序反转分页法 优化后的通用分页存储过程 sql语句 一些Select检索高级用法 SQL server 2005中新增的排序函数及应用 ...

    传智播客扫地僧视频讲义源码

    本教程共分为5个部分,第一部分是C语言提高部分,第二部分为C++基础部分,第三部分为C++进阶部分,第四部分为C、C++及数据结构基础部分,第五部分为C_C++与设计模式基础,内容非常详细. 第一部分 C语言提高部分目录...

    origami:我开发的折纸模式(仅指向其他模式的链接)

    我开发的折纸模式(带有其他模式的链接)。 如果不是我的设计,则所有图片都是我用自述文件名和文件名折叠起来的东西。 额外资源 弯折 如果您对弯曲的折叠一无所知,那是我的最爱。 我推荐。 另外,如果您不了解 ,...

    DesignPatterns

    了解和学习一下设计模式,每种模式编出一个实例 ##创建型 Factory Method(工厂方法) [Done] Abstract Factory(抽象工厂) Builder(建造者) Prototype(原型) [Done] Singleton(单例) ##结构型 Adapter Class...

    深信服桌面虚拟化测试指导书V.pdf

    独享桌面功能测试中,包括快速批量部署虚拟机测试和部署还原模式的用例等。 4.瘦客户机接入测试 在基本功能测试中,瘦客户机接入测试是其中的一个重要项目。该测试的目的是验证瘦客户机的接入能力,包括瘦客户机的...

Global site tag (gtag.js) - Google Analytics