享元模式

来源:互联网 发布:佶天鸿网络俱乐部招聘 编辑:程序博客网 时间:2024/05/23 12:52
* 0.前言

         * 我们经常使用word来编辑文档,但是在word中我们经常碰到很多汉字是我们已经输入过得,但是word内部还会让这些汉字占用内存 么?事实上没有,这些相同的汉字使用的是相同的内存地址。接下来,我们来看一个简单的程序。

public class Test {public static void  main(String [] args){String str1 = "abcd";String str2 = "abcd";System.out.println(str1 == str2);String str3 = "ab"+"cd";System.out.println(str2 == str3);String str4 = "ab";str4 +="cd";System.out.println(str2 == str4);}}

实现结果


从结果可以看到String中的新建字符串引用时,假设两个字符串管理的对象相同,那么会将两个字符串的引用指向同一内存地址。而这技术的背后实现的就是享元模式

 1.享元模式

         * 运用共享技术有效的支持大量细粒度对象的复用,系统只使用少量的对象,而这些对象的都很相似,状态的变化很小,可以实现对象的多次 复用,由于享元模式要求能够共享的对象必须是细粒度对象,因此又称为轻量级模式。


* 2.实际案例

         * 在围棋中,我们知道虽有的黑色棋子是一样的,所有的白色棋子是一样的。请用享元模式实现。


* 3.具体分析

         * 围棋中有两种棋子,分别是BlackChessPiece,WhiteChessPiece,这两个类都继承自Flyweight。对于要生产大量的细粒度 对象,我们要有工厂方法(工厂类),于是有了FlyweightFactory,用以生产享元对象。综上所述得以下几类:
         * FlyweightFactory:享元工厂类
         * ChessPiece:抽象棋子类(抽象享元类)
         * BlackChessPiece:黑色棋子类,继承自Flyweight
         * WhiteChessPiece:白色棋子类,继承自Flyweight
         * Client:客户端类
         *


* 4.具体实现

package liu.shen;/** * 客户端类 * @author Object * */public class Client {public static void main(String [] args){ ChessPiece blackChessPiece1,blackChessPiece2,whiteChessPiece1,whiteChessPiece2;  FlyweightFactory factory ; factory = FlyweightFactory.getFactoryInstance();//返回工厂实例 //通过享元工厂获取四颗棋子 blackChessPiece1 = factory.getChessPieceInstance("b"); blackChessPiece2 = factory.getChessPieceInstance("b");  whiteChessPiece1 = factory.getChessPieceInstance("w"); whiteChessPiece2 = factory.getChessPieceInstance("w");   System.out.print("blackChessPiece1 与  blackChessPiece2相同吗?"); System.out.println(blackChessPiece1 == blackChessPiece2); System.out.print("whiteChessPiece1 与 whiteChessPiece2相同吗?"); System.out.println(whiteChessPiece1 == whiteChessPiece2);  System.out.println(blackChessPiece1 == null); //这里我们可以看到blackChessPiece1以及其他的都不为Null对象 
 blackChessPiece1.display();  blackChessPiece2.display();  whiteChessPiece1.display();  whiteChessPiece2.display();  
}}
package liu.shen;/** * 黑色棋子类 * @author Object * */public class BlackChessPiece extends ChessPiece{@Overridevoid display() {// TODO Auto-generated method stubSystem.out.print("我是一枚黑色的棋子!");//coordinate.show();}}

package liu.shen;/** * 棋子类,相当于抽象享元类 * @author Object * */public abstract class ChessPiece {abstract void display();public void show(Coordinate coordinate){coordinate.show(); }}

package liu.shen;/** * 白色棋子类 * @author Object * */public class WhiteChessPiece extends ChessPiece{@Overridevoid display() {// TODO Auto-generated method stubSystem.out.print("我是一枚白色的棋子!");//coordinate.show();}}

package liu.shen;import java.util.Hashtable;/** * 享元工厂类,用以生产大量的细粒度对象 * @author Object * */public class FlyweightFactory {private static FlyweightFactory flyweightFactory = new FlyweightFactory();private static Hashtable ht;//使用Hashtable类存储享元对象,充当享元池private FlyweightFactory(){ht = new Hashtable();ChessPiece black,white;black = new BlackChessPiece();white = new WhiteChessPiece();ht.put("b", black);ht.put("w", white);}public static FlyweightFactory getFactoryInstance(){return flyweightFactory;}//根据颜色,返回棋子public  static ChessPiece getChessPieceInstance(String color){return (ChessPiece)ht.get(color);}}


*5实现结果


*6.这里我们能够看到这里就是使用工厂模式生产两个对象。但是假设在一个围棋中,有很多棋子,棋子的位置各不相同,我们该怎么实现呢?

         * 针对以上的情况,我们可以使用一个叫做Coordinate的类专门用作管理棋子的位置。为了能够实现针对抽象编程的目的,我们可以在抽象类
         * Flyweight类的中的方法使用Coordinate类的对象(依赖)来实现此功能。所以添加的类有
         * Coordinate:位置类,用以表示棋子的位置
         *
 blackChessPiece1.display(); blackChessPiece1.show(new Coordinate(1,2));  blackChessPiece2.display(); blackChessPiece2.show(new Coordinate(3,4));  whiteChessPiece1.display(); whiteChessPiece1.show(new Coordinate(5,6));  whiteChessPiece2.display();   whiteChessPiece2.show(new Coordinate(7,8));


package liu.shen;/** * 用以表示棋子的位置类 * @author Object * */public class Coordinate {private int xLabel,yLabel;//表示x轴,y轴public Coordinate(int xLabel,int yLabel){this.xLabel = xLabel;this.yLabel = yLabel;}/*xLabel与yLabel对象的get和set方法*/public int getxLabel() {return xLabel;}public void setxLabel(int xLabel) {this.xLabel = xLabel;}public int getyLabel() {return yLabel;}public void setyLabel(int yLabel) {this.yLabel = yLabel;}public void show(){System.out.println("行:"+this.getyLabel()+"列:"+this.getxLabel());}}
*7模式总结

(1)我们可以看到这里的实现只是在享元工厂中关联了抽象享元类,然后使用Hashtable类将几个抽象享元对象放到表中,在我们需要时(Client类),再调用FlyweightFactory类中

getChessPiece()方法,从而获取实例对象。

(2)在现实生活中,我们经常遇到的情况是,一些对象肯定还会有一个附加属性,而这些附加属性该怎么体现呢?这里的实现是:将附加属性Attribute作为一个类单独存在,然后

在ChessPiece类中使用一个方法,在其中使用Attribute的对象作为参数,然后调用即可。

(3)我始终觉得这个模式实现起来很别扭,不就是类似于一个原型模式嘛,但是这里的clone()方法变成了getChessPiece()方法,然后每次生产出来的对象都是一样的。因为我都是从

一个Hashtable表中得出来的,然后得到的对象就全部是一个样子(连内存地址都是一样)。

(4)所以说享元模式很简单,总结起来就这么一句话:有一个享元工厂专门负责生产本质上一样,表现层却不同的享元对象。


                                             
0 0
原创粉丝点击