zoukankan      html  css  js  c++  java
  • 设计模式(十一)享元模式

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


    核心:享元模式以共享的方式高效地支持大量细粒度对象的重用。

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

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

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

    例如:

    围棋软件设计

    每个围棋棋子都是一个对象,有如下属性:颜色、形状、大小(这些是可以共享的,称之为内部状态)

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


    享元模式实现:

    • FlyWeightFactory享元工厂类:创建并管理享元对象,享元池一般设计成键值对 
    • FlyWeight抽象享元类:通常是一个借口或抽象类。声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态
    • ConcreteFlyWeight具体享元类:为内部状态提供成员变量进行存储
    • UnsharedConcreteFlyWeight非共享享元类:不能被共享的子类可以设计为非共享享元类

    享元模式开发中的应用场景:

    • 享元模式由于其共享的特性,可以在任何“池”中操作,比如:线程池,数据库连接池
    • String类的设计也是享元模式

    优点:

    • 极大减少内存中对象的数量
    • 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
    • 外部状态相对独立,不影响内部状态

    缺点:

    • 模式较复杂,使程序逻辑复杂化
    • 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长。用时间换取了空间。

    例:

    1. 创建外部状态类

     1 package com.ztq.flyweight;
     2 
     3 /***
     4  * 外部状态UnSharedConcreteFlyWeight
     5  * @author ZTQ
     6  *
     7  */
     8 public class Coordinate {
     9     private int x, y;
    10     
    11     public Coordinate(int x, int y){
    12         this.x = x;
    13         this.y = y;
    14     }
    15 
    16     public int getX() {
    17         return x;
    18     }
    19 
    20     public void setX(int x) {
    21         this.x = x;
    22     }
    23 
    24     public int getY() {
    25         return y;
    26     }
    27 
    28     public void setY(int y) {
    29         this.y = y;
    30     }
    31     
    32     
    33 }

    2. 创建享元接口,并创建具体享元类实现该接口

     1 package com.ztq.flyweight;
     2 
     3 /***
     4  * 享元类
     5  * @author ZTQ
     6  *
     7  */
     8 public interface ChessFlyWeight {
     9     void setColor(String c);
    10     String getColor();
    11     void display(Coordinate c);
    12 }
    13 
    14 class ConcreteChess implements ChessFlyWeight{
    15     
    16     private String color;
    17     
    18     public ConcreteChess(String color){
    19         this.color = color;
    20     }
    21     
    22     @Override
    23     public void setColor(String c) {
    24         this.color = c;
    25     }
    26 
    27     @Override
    28     public String getColor() {
    29         return color;
    30     }
    31 
    32     @Override
    33     public void display(Coordinate c) {
    34         System.out.println("棋子颜色:" + color);
    35         System.out.println("棋子位置:" + c.getX() + "---" + c.getY());
    36     }
    37     
    38 }

    3. 创建享元工厂类

     1 package com.ztq.flyweight;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 /***
     7  * 享元工厂类
     8  * @author ZTQ
     9  *
    10  */
    11 public class ChessFlyWeightFactory {
    12     //享元池
    13     private static Map<String, ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();
    14     
    15     public static ChessFlyWeight getChess(String color){
    16         if(map.get(color) != null){
    17             return map.get(color);
    18         }
    19         else{
    20             ChessFlyWeight cfw = new ConcreteChess(color);
    21             map.put(color, cfw);
    22             return cfw;
    23         }
    24     }
    25 }

    4. 创建测试类Client

     1 package com.ztq.flyweight;
     2 
     3 public class Client {
     4     public static void main(String[] args) {
     5         ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
     6         ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
     7         System.out.println(chess1);
     8         System.out.println(chess2);
     9         
    10         System.out.println("增加外部状态的处理");
    11         chess1.display(new Coordinate(10, 10));
    12         chess2.display(new Coordinate(20, 20));
    13         
    14     }
    15 }

    结果:

    com.ztq.flyweight.ConcreteChess@55f33675
    com.ztq.flyweight.ConcreteChess@55f33675
    增加外部状态的处理
    棋子颜色:黑色
    棋子位置:10---10
    棋子颜色:黑色
    棋子位置:20---20

    UML图:

  • 相关阅读:
    一步一步学Silverlight 2系列(16):数据与通信之JSON
    一步一步学Silverlight 2系列(15):数据与通信之ASMX
    谈一谈做iOS播放器库开发所涉及的知识点
    回顾大学生活
    iOS 简化冗余代码
    修正DejalActivityView在iOS8之前系统上存在的Bug
    2015年,你要做什么(一)
    iOS学习笔记
    IOS SDK详解
    iOS开发进阶
  • 原文地址:https://www.cnblogs.com/zhangtianq/p/6096061.html
Copyright © 2011-2022 走看看