您的位置:首页 > 编程语言 > Go语言

GOF之享元模式

2016-08-12 21:50 344 查看
                           享元模式学习






 [b]

[/b]

 

 

 

   其实享元模式在很多的框架中都是使用得很多的。享元模式又叫做FlyWeight,又叫做

轻量级。比如我们经常说什么轻量级比赛等。在很多的情况下,享元模式可以很好节省我们的内存。其实,享元模式是利用了以时间来换取空间的策略。其实,在很多的地方,

都使用了享元模式,比如我们经常说的String类型的使用,还有就是线程池的使用等等很多的地方。下面我以一个简单的例子来做说明。








 

其实,利用享元模式的最关键的步骤是分清楚什么是内部状态,什么是外部状态。所谓的

内部状态就是可以共享的状态,这些属性在所有的对象中都是一样的。而所谓的外部的状态就是不可以共享的状态。这些状态在对象中是不一样的。外部状态会随外面的环境的变化而变化。我们一上图中的棋子为例。其实,如果我们利用了享元模式的话,这么多的对象,其实对我们来说就是俩个对象。黑色棋子和白色棋子。就像上面所说的,每个围棋棋子其实

都是一个对象。其中,颜色,形状,大小,这些是可以共享的,对于黑色棋子来说,这些属性在每一个棋子中都是一样的。对于白色棋子来说,这些属性在每一个棋子中也是一样的。

那么什么事外部状态呢?其实每一个棋子的位置就是外部状态,因为棋子的位置都是不一样的。每一个棋子的状态都是不可以共享的。那么我们如何利用享元模式来设计上面的例子呢?其实也是蛮简单的。








   

 

  首先,我们需要设计一个抽象享元类。这个享元类的最重要的方法是可以向外界提供对象的内部状态,并且还可以设置外部状态。

  其次就是unsharedConcreteFlyWeight类。这个类的主要的任务是保存一些外部状态,这些

状态是不可以被共享的。

  还有就是ConcreteFlyWeight享元类,为内部状态提供成员变量进行存储。

   最重要的还是需要有一个享元工厂类。这个类的主要作用是负责创建并且管理共享元对象。这是最重要的。

   

 

 

 

接下来我们就来看一下这个例子该如何设计:

package com.bjsxt.flyweight;

 

/**

 * 享元类
FlyWeight抽象享元类


 * @author Administrator

 *

 */

public interface ChessFlyWeight {

void setColor(String c);

String getColor();

void display(Coordinate c);

}

 

 

//ConcreteFlyWeight享元类

class ConcreteChess implements ChessFlyWeight {

 

private String color;

public ConcreteChess(String color) {

super();

this.color = color;

}

 

@Override

public void display(Coordinate c) {

System.out.println("棋子颜色:"+color);

System.out.println("棋子位置:"+c.getX()+"----"+c.getY());

}

 

@Override

public String getColor() {

return color;

}

 

@Override

public void setColor(String c) {

this.color = c;

}

}

 

 

//unsharedConcreteFlyWeight类

package com.bjsxt.flyweight;

 

/**

 * 外部状态UnSharedConcreteFlyWeight

 * @author Administrator

 *

 */

public class Coordinate {

private int x,y;

 

public Coordinate(int x, int y) {

super();

this.x = x;

this.y = y;

}

 

public int getX() {

return x;

}

 

public void setX(int x) {

this.x = x;

}

 

public int getY() {

return y;

}

 

public void setY(int y) {

this.y = y;

}

}

 

 

//享元工厂类

package com.bjsxt.flyweight;

 

import java.util.HashMap;

import java.util.Map;

 

/**

 * 享元工厂类

 * @author Administrator

 *

 */

public class ChessFlyWeightFactory {

//享元池。一般我们会利用键值对Map来进行设计。

private static Map<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();

public static ChessFlyWeight  getChess(String color){

if(map.get(color)!=null){

return map.get(color);

}else{

ChessFlyWeight cfw = new ConcreteChess(color);

map.put(color, cfw);

return cfw;

}

}

}

 

最后我们来看一下,我们是如何利用这个类的:

package com.bjsxt.flyweight;

 

public class Client {

public static void main(String[] args) {

ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");

ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");

System.out.println(chess1);

System.out.println(chess2);

System.out.println("增加外部状态的处理===========");

chess1.display(new Coordinate(10, 10));

chess2.display(new Coordinate(20, 20));

}

}

 

在这里我想说的一点就是其实chess1和chess2是同一个对象的。那么多的棋子其实如果是利用了享元模式的话,其实也就是俩个对象而已。这就大大节省了内存。但是,效率会有一定的降低。这是无可避免的。这是利用了时间换取空间的策略。

 [b]

[/b]

 

 

 

最后想提的一点是,如果在平时的开发当中,遇到了诸如什么什么池的话,那么这个池一般指的就是容器之类的东西了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: