【设计模式】享元模式(Flyweight)

概述

  • 享元模式是以共享的方式高效地支持大量的细粒度对象。
  • 享元对象能做到共享的关键是区分内部状态和外部状态。内部状态是存储在享元对象内部并且不会随环境改变而改变。因此内部状态可以共享。

享元模式结构图

【设计模式】享元模式(Flyweight)_第1张图片

示意性代码

namespace 享元模式
{
    abstract class Flyweight
    {
        public abstract void Operation(int extrinsicstate);
    }

    class ConcreteFlyweight:Flyweight
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("具体Flyweight:" + extrinsicstate);
        }
    }

    class UnsharedConcreteFlyweight:Flyweight
    {
        public override void Operation(int extrinsicstate)
        {
            Console.WriteLine("不共享的具体Flyweight:" + extrinsicstate);
        }
    }

    class FlyweightFactory
    {
        private Hashtable flyweights = new Hashtable();

        public FlyweightFactory()
        {
            flyweights.Add("X", new ConcreteFlyweight());
            flyweights.Add("Y", new ConcreteFlyweight());
            flyweights.Add("Z", new ConcreteFlyweight());
        }

        public Flyweight GetFlyweight(string key)
        {
            return (Flyweight)flyweights[key];
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            int extrinsicstate = 22;

            FlyweightFactory f = new FlyweightFactory();

            Flyweight fx = f.GetFlyweight("X");
            fx.Operation(--extrinsicstate);

            Flyweight fy = f.GetFlyweight("Y");
            fx.Operation(--extrinsicstate);

            Flyweight fz = f.GetFlyweight("Z");
            fx.Operation(--extrinsicstate);

            UnsharedConcreteFlyweight uf = new UnsharedConcreteFlyweight();

            uf.Operation(--extrinsicstate);

            Console.Read();
        }
    }
}

享元模式重点

共享内部状态,加载外部状态
变与不变

  • 享元模式设计的重点就在分离变与不变。把一个对象的状态分成内部状态的外部状态,内部状态是不变的,外部状态是可变的。然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
  • 分离变与不变是软件设计上最基本的方式之一,比如预留接口:一个常见的原因就是这里存在变化,可能在今后需要扩展或者是改变已有的实现,因此预留接口作为“可插入性的保证”。

享元模式使用情况

  • 一个系统有大量的对象。
  • 这些对象耗费大量的内存
  • 这些对象的状态中的大部分都可以外部消化。
  • 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替。

使用享元模式需要维护一个记录了系统已有的所有享元的表,而这需要耗费资源。因此,应当在有足够多的享元实例可供共享时才值得使用享元模式。

优点

大幅度地降低内存中对象的数量,节省内存空间

缺点

  • 享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
  • 享元模式将向原对象的状态外部化,而读取外部状态使得运行时间变长。

本质

分离与共享

实例

ps:仅代表个人思路
【问题】
使用享元模式实现五子棋
【代码】

public class Location {
	
	private int x,y;
	private String color;

	public Location(int x, int y,String color) {
		super();
		this.x = x;
		this.y = y;
		this.color=color;
	}

	public Location() {}

	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;
	}
	
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
	
}

public abstract class Chessman {
	
	private Location l;
	
	public Chessman(Location l) {
		super();
		this.l = l;
	}
	
	public Location getL() {
		return l;
	}

	public void setL(Location l) {
		this.l = l;
	}

	abstract public void put();

}

public class WhiteChessman extends Chessman {
	
	public WhiteChessman(Location l) {
		super(l);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void put() {
		System.out.println("在("+super.getL().getX()+","+super.getL().getY()+")的位置放一个白子。");
	}

}

public class BlackChessman extends Chessman {

	public BlackChessman(Location l) {
		super(l);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void put() {
		System.out.println("在("+super.getL().getX()+","+super.getL().getY()+")的位置放一个黑子。");
	}

}

public class ChessFactory {
	
	private List<Chessman> l=new ArrayList<Chessman>();
	
	public Chessman getChessman(Location t) {
		Chessman c=null;
		if(t.getColor().equals("black"))
			c=new BlackChessman(t);
		else
			c=new WhiteChessman(t);
		int f=0;
		if(!l.isEmpty()) {
			for(Chessman i:l) {
				if(i.getL().equals(t)) {
					f=1;
				}
			}
			if(f==0)
				l.add(c);
		}else {
			l.add(c);
		}
		return c;
	}

	public List<Chessman> getL() {
		return l;
	}

	public int getNum() {
		return l.size();
	}

}

public class Client {

	public static void main(String[] args) {
		ChessFactory cf=new ChessFactory();
		
		Location l1=new Location(1,2,"black"); 
		Chessman c1=cf.getChessman(l1);
		c1.put();
		
		Location l2=new Location(1,2,"white"); 
		Chessman c2=cf.getChessman(l2);
		c2.put();

	}

}

【UML】
【设计模式】享元模式(Flyweight)_第2张图片

你可能感兴趣的:(设计模式,设计模式)