<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>http://wiki.eijux.com/index.php?action=history&amp;feed=atom&amp;title=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F</id>
	<title>设计模式：享元模式 - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.eijux.com/index.php?action=history&amp;feed=atom&amp;title=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F"/>
	<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F&amp;action=history"/>
	<updated>2026-05-15T15:04:01Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.38.2</generator>
	<entry>
		<id>http://wiki.eijux.com/index.php?title=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F&amp;diff=2955&amp;oldid=prev</id>
		<title>Eijux：​建立内容为“category:设计模式  == 关于 == &lt;pre&gt; 在面向对象程序设计过程中，有时会面临要创建大量相同或相似对象实例的问题。创建…”的新页面</title>
		<link rel="alternate" type="text/html" href="http://wiki.eijux.com/index.php?title=%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F&amp;diff=2955&amp;oldid=prev"/>
		<updated>2021-05-08T16:14:19Z</updated>

		<summary type="html">&lt;p&gt;建立内容为“&lt;a href=&quot;/%E5%88%86%E7%B1%BB:%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F&quot; title=&quot;分类:设计模式&quot;&gt;category:设计模式&lt;/a&gt;  == 关于 == &amp;lt;pre&amp;gt; 在面向对象程序设计过程中，有时会面临要创建大量相同或相似对象实例的问题。创建…”的新页面&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[category:设计模式]]&lt;br /&gt;
&lt;br /&gt;
== 关于 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
在面向对象程序设计过程中，有时会面临要创建大量相同或相似对象实例的问题。创建那么多的对象将会耗费很多的系统资源，它是系统性能提高的一个瓶颈。&lt;br /&gt;
&lt;br /&gt;
例如，围棋和五子棋中的黑白棋子，图像中的坐标点或颜色，局域网中的路由器、交换机和集线器，教室里的桌子和凳子等。这些对象有很多相似的地方，如果能把它们相同的部分提取出来共享，则能节省大量的系统资源，这就是享元模式的产生背景。&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
享元（Flyweight）模式的定义：'''运用共享技术来有效地支持大量细粒度对象的复用'''。【将相同的部分提取出来复用】&lt;br /&gt;
* 它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销，从而提高系统资源的利用率。&lt;br /&gt;
&lt;br /&gt;
=== 优点和缺点 ===&lt;br /&gt;
优点：&lt;br /&gt;
* '''相同对象只要保存一份'''，这降低了系统中对象的数量，从而降低了系统中细粒度对象给内存带来的压力。&lt;br /&gt;
&lt;br /&gt;
缺点：&lt;br /&gt;
* 为了使对象可以共享，需要将一些不能共享的状态外部化，这将增加程序的复杂性。&lt;br /&gt;
* 读取享元模式的外部状态会使得运行时间稍微变长。&lt;br /&gt;
&lt;br /&gt;
=== 应用场景 ===&lt;br /&gt;
当系统中多处需要同一组信息时，可以把这些信息封装到一个对象中，然后对该对象进行缓存，这样，一个对象就可以提供给多出需要使用的地方，避免大量同一对象的多次创建，降低大量内存空间的消耗。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
享元模式其实是工厂方法模式的一个改进机制，享元模式同样要求创建一个或一组对象，并且就是通过工厂方法模式生成对象的，只不过享元模式为工厂方法模式增加了缓存这一功能。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
享元模式是通过减少内存中对象的数量来节省内存空间的，所以以下几种情形适合采用享元模式：&lt;br /&gt;
* 系统中存在大量相同或相似的对象，这些对象耗费大量的内存资源。&lt;br /&gt;
* 大部分的对象可以按照内部状态进行分组，且可将不同部分外部化，这样每一个组只需保存一个内部状态。&lt;br /&gt;
* 由于享元模式需要额外维护一个保存享元的数据结构，所以应当在有足够多的享元实例时才值得使用享元模式。&lt;br /&gt;
&lt;br /&gt;
== 结构与实现 ==&lt;br /&gt;
享元模式的定义提出了两个要求，细粒度和共享对象。因为要求细粒度，所以不可避免地会使对象数量多且性质相近，此时我们就将这些对象的信息分为两个部分：&lt;br /&gt;
# '''内部状态'''：指对象共享出来的信息，存储在享元信息内部，并且不回随环境的改变而改变；&lt;br /&gt;
# '''外部状态'''：指对象得以依赖的一个标记，随环境的改变而改变，不可共享。&lt;br /&gt;
&lt;br /&gt;
比如，连接池中的连接对象，保存在连接对象中的用户名、密码、连接URL等信息，在创建对象的时候就设置好了，不会随环境的改变而改变，这些为内部状态。而当每个连接要被回收利用时，我们需要将它标记为可用状态，这些为外部状态。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
享元模式的本质是缓存共享对象，降低内存消耗。&lt;br /&gt;
&lt;br /&gt;
=== 结构 ===&lt;br /&gt;
享元模式的主要角色如下：&lt;br /&gt;
# '''抽象享元'''（Flyweight）角色：是所有的具体享元类的基类，为具体享元规范需要实现的公共接口，非享元的外部状态以参数的形式通过方法传入。&lt;br /&gt;
# '''具体享元'''（Concrete Flyweight）角色：实现抽象享元角色中所规定的接口。&lt;br /&gt;
# '''非享元'''（Unsharable Flyweight)角色：是不可以共享的外部状态，它以参数的形式注入具体享元的相关方法中。&lt;br /&gt;
# '''享元工厂'''（Flyweight Factory）角色：负责创建和管理享元角色。当客户对象请求一个享元对象时，享元工厂检査系统中是否存在符合要求的享元对象，如果存在则提供给客户；如果不存在的话，则创建一个新的享元对象。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
其结构如下：&lt;br /&gt;
: [[File:设计模式：享元模式.png|600px]]&lt;br /&gt;
其中：&lt;br /&gt;
* 抽象享元角色，里面包含了享元方法“operation(UnsharedConcreteFlyweight state)”，'''非享元的外部状态以参数的形式通过该方法传入'''；&lt;br /&gt;
* 客户角色通过享元工厂获取具体享元，并访问具体享元的相关方法。&lt;br /&gt;
&lt;br /&gt;
=== 实现 ===&lt;br /&gt;
其代码如下：&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; line highlight=&amp;quot;3&amp;quot;&amp;gt;&lt;br /&gt;
//抽象享元角色&lt;br /&gt;
interface Flyweight {&lt;br /&gt;
    public void operation(UnsharedConcreteFlyweight state);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//具体享元角色&lt;br /&gt;
class ConcreteFlyweight implements Flyweight {&lt;br /&gt;
    private String key;&lt;br /&gt;
    ConcreteFlyweight(String key) {&lt;br /&gt;
        this.key = key;&lt;br /&gt;
        System.out.println(&amp;quot;具体享元&amp;quot; + key + &amp;quot;被创建！&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    public void operation(UnsharedConcreteFlyweight outState) {&lt;br /&gt;
        System.out.print(&amp;quot;具体享元&amp;quot; + key + &amp;quot;被调用，&amp;quot;);&lt;br /&gt;
        System.out.println(&amp;quot;非享元信息是:&amp;quot; + outState.getInfo());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//非享元角色&lt;br /&gt;
class UnsharedConcreteFlyweight {&lt;br /&gt;
    private String info;&lt;br /&gt;
    UnsharedConcreteFlyweight(String info) {&lt;br /&gt;
        this.info = info;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public String getInfo() {&lt;br /&gt;
        return info;&lt;br /&gt;
    }&lt;br /&gt;
    public void setInfo(String info) {&lt;br /&gt;
        this.info = info;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//享元工厂角色&lt;br /&gt;
class FlyweightFactory {&lt;br /&gt;
    private HashMap&amp;lt;String, Flyweight&amp;gt; flyweights = new HashMap&amp;lt;String, Flyweight&amp;gt;();&lt;br /&gt;
    &lt;br /&gt;
    public Flyweight getFlyweight(String key) {&lt;br /&gt;
        Flyweight flyweight = (Flyweight) flyweights.get(key);&lt;br /&gt;
        if (flyweight != null) {&lt;br /&gt;
            System.out.println(&amp;quot;具体享元&amp;quot; + key + &amp;quot;已经存在，被成功获取！&amp;quot;);&lt;br /&gt;
        } else {&lt;br /&gt;
            flyweight = new ConcreteFlyweight(key);&lt;br /&gt;
            flyweights.put(key, flyweight);&lt;br /&gt;
        }&lt;br /&gt;
        return flyweight;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public class FlyweightPattern {&lt;br /&gt;
    public static void main(String[] args) {&lt;br /&gt;
        FlyweightFactory factory = new FlyweightFactory();&lt;br /&gt;
        Flyweight f01 = factory.getFlyweight(&amp;quot;a&amp;quot;);&lt;br /&gt;
        Flyweight f02 = factory.getFlyweight(&amp;quot;a&amp;quot;);&lt;br /&gt;
        Flyweight f03 = factory.getFlyweight(&amp;quot;a&amp;quot;);&lt;br /&gt;
        Flyweight f11 = factory.getFlyweight(&amp;quot;b&amp;quot;);&lt;br /&gt;
        Flyweight f12 = factory.getFlyweight(&amp;quot;b&amp;quot;);&lt;br /&gt;
        f01.operation(new UnsharedConcreteFlyweight(&amp;quot;第1次调用a。&amp;quot;));&lt;br /&gt;
        f02.operation(new UnsharedConcreteFlyweight(&amp;quot;第2次调用a。&amp;quot;));&lt;br /&gt;
        f03.operation(new UnsharedConcreteFlyweight(&amp;quot;第3次调用a。&amp;quot;));&lt;br /&gt;
        f11.operation(new UnsharedConcreteFlyweight(&amp;quot;第1次调用b。&amp;quot;));&lt;br /&gt;
        f12.operation(new UnsharedConcreteFlyweight(&amp;quot;第2次调用b。&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
: &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; highlight=&amp;quot;&amp;quot;&amp;gt;&lt;br /&gt;
具体享元a被创建！&lt;br /&gt;
具体享元a已经存在，被成功获取！&lt;br /&gt;
具体享元a已经存在，被成功获取！&lt;br /&gt;
具体享元b被创建！&lt;br /&gt;
具体享元b已经存在，被成功获取！&lt;br /&gt;
具体享元a被调用，非享元信息是:第1次调用a。&lt;br /&gt;
具体享元a被调用，非享元信息是:第2次调用a。&lt;br /&gt;
具体享元a被调用，非享元信息是:第3次调用a。&lt;br /&gt;
具体享元b被调用，非享元信息是:第1次调用b。&lt;br /&gt;
具体享元b被调用，非享元信息是:第2次调用b。&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 模式的扩展 ==&lt;br /&gt;
在实际使用过程中，存在两种特殊的享元模式：&lt;br /&gt;
# '''单纯享元'''模式：&lt;br /&gt;
#: 这种享元模式中的所有的具体享元类都是可以共享的，不存在非共享的具体享元类；【无“非享元角色”】&lt;br /&gt;
#: [[File:设计模式：享元模式：单纯享元模式.png|400px]]&lt;br /&gt;
# '''复合享元'''模式：&lt;br /&gt;
#: 这种享元模式中的有些享元对象是由一些单纯享元对象组合而成的，它们就是复合享元对象；【“具体享元角色”是多个“单纯享元”的组合】&lt;br /&gt;
#* 虽然复合享元对象本身不能共享，但它们可以分解成单纯享元对象再被共享。&lt;br /&gt;
#: [[File:设计模式：享元模式：复合享元模式.png|500px]]&lt;/div&gt;</summary>
		<author><name>Eijux</name></author>
	</entry>
</feed>