zoukankan      html  css  js  c++  java
  • GOF23设计模式之享元模式(flyweight)

    一、享元模式概述

      内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的对象,可以通过享元模式,节省内存。

      享元模式核心:

        (1)享元模式可以共享的、方式高效的支持大量细粒度对象的重用; 

        (2)享元对象能做到共享的关键是区分了内部状态和外部状态:

            ① 内部状态:可以共享,不会随环境变化而改变

            ② 外部状态:不能共享,会随环境变化而改变

    二、享元模式实现

      (1)FlyWeightFactory享元工厂类

          创建并管理享元对象,享元池一般设计成键值对。

      (2)FlyWeight抽象享元类

          通常是一个接口,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。

      (3)ConcreteFlyWeight具体享元类

          内部状态提供成员变量进行存储。

      (4)UnShareConcreteFlyWeight非共享享元类

          不能被共享的子类可以设计成非共享享元类。

    三、元模式场景导入示例代码

      场景:围棋中每一个棋子都是一个对象。棋子有如下属性:

           颜色 状态 大小(这些是可以共享的)称之为:内部状态

             位置(这是不可以共享的)称之为:外部状态

     1 /**
     2  * 抽象享元类FlyWeight
     3  * @author CL
     4  *
     5  */
     6 public interface ChessFlyWeight {
     7     void setColor(String color);
     8     String getColor();
     9     void display(Coordinate c);
    10 }
    11 
    12 /**
    13  * ConcreteFlyWeight具体享元类
    14  * 内部状态
    15  * @author CL
    16  *
    17  */
    18 class ConcreteChess implements ChessFlyWeight {
    19 
    20     private String color;
    21     
    22     public ConcreteChess(String color) {
    23         this.color = color;
    24     }
    25 
    26     @Override
    27     public void setColor(String color) {
    28         this.color = color;
    29     }
    30 
    31     @Override
    32     public String getColor() {
    33         return color;
    34     }
    35 
    36     @Override
    37     public void display(Coordinate c) {
    38         System.out.println("棋子的颜色: "+color);
    39         System.out.println("棋子的位置: ["+c.getX()+","+c.getY()+"]");
    40     }
    41     
    42 }
     1 import java.util.HashMap;
     2 import java.util.Map;
     3 
     4 /**
     5  * 享元工厂类
     6  * @author CL
     7  *
     8  */
     9 public class ChessFlyWeightFactory {
    10     //享元池
    11     private static Map<String, ChessFlyWeight> map = 
    12             new HashMap<String, ChessFlyWeight>();;
    13 
    14     public static ChessFlyWeight getChess(String color) {
    15         if (map.get(color) != null) {
    16             return map.get(color);
    17         } else {
    18             ChessFlyWeight cfw = new ConcreteChess(color);
    19             map.put(color, cfw);
    20             return cfw;
    21         }
    22     }
    23     
    24 }
     1 /**
     2  * 外部状态
     3  *     UnShareFlyWeight非共享享元类
     4  * @author CL
     5  *
     6  */
     7 public class Coordinate {
     8     private int x, y;
     9 
    10     public Coordinate(int x, int y) {
    11         this.x = x;
    12         this.y = y;
    13     }
    14 
    15     public int getX() {
    16         return x;
    17     }
    18 
    19     public void setX(int x) {
    20         this.x = x;
    21     }
    22 
    23     public int getY() {
    24         return y;
    25     }
    26 
    27     public void setY(int y) {
    28         this.y = y;
    29     }
    30 }

      测试:

     1 /**
     2  * 测试享元模式
     3  * @author CL
     4  *
     5  */
     6 public class Client {
     7     
     8     public static void main(String[] args) {
     9         ChessFlyWeight c1 = ChessFlyWeightFactory.getChess("黑色");
    10         ChessFlyWeight c2 = ChessFlyWeightFactory.getChess("黑色");
    11         System.out.println(c1);
    12         System.out.println(c2);    //c1 和 c2 是同一对象
    13         
    14         System.out.println("--------------------");
    15         c1.display(new Coordinate(10, 10));
    16         c2.display(new Coordinate(20, 20));
    17     }
    18 
    19 }

      控制台输出:

    com.caolei.flyweight.ConcreteChess@759ebb3d
    com.caolei.flyweight.ConcreteChess@759ebb3d
    --------------------
    棋子的颜色: 黑色
    棋子的位置: [10,10]
    棋子的颜色: 黑色
    棋子的位置: [20,20]

    四、享元模式优缺点

      优点:

        (1)极大的减少内存中对象的数量;

        (2)相同或相似对象内存中只存一份,极大的节约资源,提高系统性能;

        (3)外部状态相对独立,不影响内部状态。

      缺点:

        (1)模式较复杂,使程序逻辑复杂化;

        (2)为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间较长,用时间换空间。

    五、享元模式常见开发应用场景

      (1)享元模式由于其共享的特性,可以在任何“池”中操作,比如:线程池、数据库连接池;

      (2)String类的设计也是享元模式;

      (3)…………

  • 相关阅读:
    《Linux内核设计与实现》读书笔记(十一) 定时器和时间管理
    《Linux内核设计与实现》读书笔记(十) 内核同步方法
    《Linux内核设计与实现》读书笔记(八) 中断下半部的处理
    《Linux内核设计与实现》读书笔记(七) 中断处理
    《Linux内核设计与实现》读书笔记(九) 内核同步介绍
    SQL Server数据库中使用sql脚本删除指定表的列
    如何删除在Excel中存在的无效的链接呢
    SQL Server游标使用快速上手
    SQL Server中查询某列所在的数据库中所在的表
    WinAPI: SetTimer、KillTimer 创建与移除高性能定时器
  • 原文地址:https://www.cnblogs.com/cao-lei/p/8327935.html
Copyright © 2011-2022 走看看