一、概念
享元模式,运用共享技术有效地支持大量细粒度的对象的复用。
二、类图及基本代码
//抽象享元类
public abstract class Flywight {
public abstract void Operation(int extrinsicstate);
}
//具体享元类
public class ConcreteFlyweight extends Flywight{
@Override
public void Operation(int extrinsicstate) {
System.out.println("具体Flyweight:"+extrinsicstate);
}
}
//不需要共享的Flyweight子类
public class UnsharedConcreteFlyweight extends Flywight{
@Override
public void Operation(int extrinsicstate) {
System.out.println("不共享的具体Flyweight:"+extrinsicstate);
}
}
//享元工厂类
public class FlyweightFactory {
private Hashtable<String, Flywight> flyweights=new Hashtable<>();
public FlyweightFactory(){
flyweights.put("X", new ConcreteFlyweight());
flyweights.put("Y", new ConcreteFlyweight());
flyweights.put("Z", new ConcreteFlyweight());
}
//根据客户端的请求,返回要获得的实例
public Flywight GetFlyweight(String key){
return (Flywight)flyweights.get(key);
}
}
//客户端
public class Client {
public static void main(String[] args) {
int extrinsicstate=22;
FlyweightFactory factory=new FlyweightFactory();
Flywight fx=factory.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flywight fy=factory.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flywight fz=factory.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
Flywight flywight=new UnsharedConcreteFlyweight();
flywight.Operation(--extrinsicstate);
}
}
三、实例之网站共享
//外部状态类
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
//抽象享元类--->接受外部状态
public abstract class WebSite {
public abstract void Use(User user);
}
//具体享元类
public class ConcreteWebSite extends WebSite {
private String name = "";
public ConcreteWebSite(String name) {
this.name = name;
}
@Override
public void Use(User user) {
System.out.println("网站分类:" + name + " 用户名:" + user.getName());
}
}
//网站共产类
public class WebSiteFactory {
private Hashtable<String, WebSite> flyweights = new Hashtable<>();
//根据客户端的请求返回相应的网站实例
public WebSite GetWebSiteCategory(String key) {
if (!flyweights.contains(key)) {
flyweights.put(key, new ConcreteWebSite(key));
}
return (WebSite) flyweights.get(key);
}
public int GetWebSiteCount(){
return flyweights.size();
}
}
//客户端
public class Client {
public static void main(String[] args) {
WebSiteFactory webSiteFactory=new WebSiteFactory();
WebSite fx=webSiteFactory.GetWebSiteCategory("产品展示");
fx.Use(new User("小明"));
WebSite fy=webSiteFactory.GetWebSiteCategory("产品展示");
fy.Use(new User("小乐"));
WebSite fz=webSiteFactory.GetWebSiteCategory("产品展示");
fz.Use(new User("小米"));
WebSite f1=webSiteFactory.GetWebSiteCategory("博客");
f1.Use(new User("喵喵"));
WebSite f2=webSiteFactory.GetWebSiteCategory("博客");
f2.Use(new User("红红"));
System.out.println("网站分类有:"+webSiteFactory.GetWebSiteCount());
}
}
四、总结
内部状态:在享元对象内部且不会随着环境改变而改变的共享部分。
外部状态:随着环境改变而改变的,不可共享的状态。
在上述案例中,内部状态即为网站的类别,如博客,产品展示,这些都是可以共享的。
外部状态即为用户,因为登录不同类别的网站时,用户的登录是不可共享的,则用专门的用户类来处理。
优点:大幅度地降低内存中对象的数量,实现了部分对象的共享。
缺点:享元模式使系统变得复杂。为了实现对象共享,要将一些状态外部化,使得程序逻辑复杂化。
因此只有在有足够多的对象实例可供共享时才值得用享元模式。如围棋,有大量的棋子对象,内部状态只有颜色,即黑色,白色。外部状态有棋子的坐标,可用一个坐标类来处理。
Among those people that appear in our life, some are to teach us, some to comfortus, some to share and some to love.