FlyweightPattern(23种设计模式之一)


设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大原则(6):开闭原则

参考书籍:设计模式-可复用面向对象软件基础(黑皮书)

享元模式,以共享的方式高效地支持大量的细粒度对象。通过复用内存中已存在的对象,降低系统创建对象实例的性能消耗。

简单的典型实例:以黑白五子棋对弈为例,获取每个棋子的状态,然而我们不可能为每个棋子都建立一个对象,这样内存开销太大,这样关键就在于抽象出每个棋子的内部状态和外部状态,将其的状态分离。

FlyweightPattern,UML抽象图百度找,代码实现如下

使用享元模式设计以黑白五子棋对弈

抽象细粒度对象类

package FlyweightPattern;
public abstract class Chessman {
	private String color;
	private int x;
	private int y;
	public Chessman(String color){
		this.color = color;
	}
	public void setPosition(int x,int y){
		this.x = x;
		this.y = y;
	}
	public String getColor(){
		return color;
	}
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
}

细粒度具体对象类

package FlyweightPattern;
public class BlackChessman extends Chessman {
	public BlackChessman() {
		super("黑棋子");
		System.out.println("创建黑棋子");
	}
}
package FlyweightPattern;
public class WhiteChessman extends Chessman {
	public WhiteChessman() {
		super("白棋子");
		System.out.println("创建白棋子");
	}
}

粒度工厂类

package FlyweightPattern;
import java.util.Hashtable;
public class ChessmanFactory {
	private static ChessmanFactory chessmanFactory = new ChessmanFactory();
	//缓存存放共享对象
	Hashtable<Character,Chessman> cache = new Hashtable<Character,Chessman>();
	public static ChessmanFactory getInstance(){
		return chessmanFactory;
	}
	//获取棋子
	public Chessman getChessman(char c){
		Chessman chessman = this.cache.get(c);
		if(chessman==null){
			if(c=='W'){
				chessman = new WhiteChessman();
			}else if(c=='B'){
				chessman = new BlackChessman();
			}
			cache.put(c, chessman);
		}
		return chessman;
	}
}

测试类

package FlyweightPattern;
public class Test {
	public static void main(String[] args) {
		ChessmanFactory factory=ChessmanFactory.getInstance();
		Chessman chessman1=factory.getChessman('W');
		chessman1.setPosition(1, 1);
		System.out.println(chessman1.getColor()+" ("+chessman1.getX()+","+chessman1.getY()+")");
		Chessman chessman2=factory.getChessman('W');
		chessman2.setPosition(2, 2);
		System.out.println(chessman2.getColor()+" ("+chessman2.getX()+","+chessman2.getY()+")");
		Chessman chessman3=factory.getChessman('B');
		chessman3.setPosition(3, 3);
		System.out.println(chessman3.getColor()+" ("+chessman3.getX()+","+chessman3.getY()+")");
		Chessman chessman4=factory.getChessman('B');
		chessman4.setPosition(4, 4);
		System.out.println(chessman4.getColor()+" ("+chessman4.getX()+","+chessman4.getY()+")");
	}
}

享元模式的两种状态:内蕴状态和外蕴状态
1.内蕴状态(内部状态):
享元模式的内蕴状态是不会随环境的改变而改变的,是存储在享元对象内部的状态信息,因此内蕴状态是可以共享的,对于任何一个享元对象来讲,它的值是完全相同的。就像上面例子中的“黑子”和“白子”,它代表的状态就是内蕴状态。
2.外蕴状态(外部状态)
外蕴状态会随环境的变化而改变的,因此是不可共享的状态,对于不同的享元对象来讲,它的值可能是不同的。享元对象的外蕴状态必须由客户端保存,在享元对象被创建之后,需要使用的时候再传入到享元对象的内部。就像五子棋的位置信息,代表的状态就是享元对象的外蕴状态。


享元模式关键就在内部状态与外部状态的分离,在这里,场景就是棋盘,棋子的坐标就是外部状态(不可共享),棋子的颜色就是独立于场景的内部状态(可被共享),用户对象负责在有必要的时候将外部状态传递给享元


posted @ 2017-04-12 17:26  纪伟  阅读(485)  评论(1编辑  收藏  举报