享元模式,高效的支持细粒度的对象。享元对象能做到共享的关键是区分内蕴状态和外蕴状态,一个内蕴状态是存储在享元对象内部的,并不会随环境的变化而变化,因此,一个享元可以具有内蕴状态并可以共享。一个外蕴状态是随环境变化而变化的,不可以共享。享元对象的外蕴状态必须由客户端保存,并在享元对象后被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不能影响内蕴状态,即相互独立。
上面说了一大堆非常抽象,用gof的例子来说,例如一个文本编辑器,在上面可以编辑字母,共有52个字母,含大小写,如果它要写1000字母的文章,则有接近20倍的字母都会重复,即没写一个字母,会实例化一次字母的父类。这样就会花费很多资源,并且每一个字母都有可能带不同的样式。从这分析,我们就可以使用享元模式。首先字母就可以作为内蕴状态,因为他们是固定的52个,并且如果再次使用重复字母,我们就可以通过共享来实现,而字母的样式我们就认为它是外蕴状态,是可以随之改变的。
接下来,看看代码。
定义接口,并创建一个改变字体样式方法
public interface Flyweight {
public void operation(String state);
}
实现此接口
public class ConcerteFlyweight implements Flyweight{
//内蕴状态
private Character intrinsicState = null;
//传进来的参数属于外晕状态
public ConcerteFlyweight(Character state) {
this.intrinsicState = state;
}
public void operation(String state) {
System.out.println("intrinsicState="+intrinsicState+",Extrinsic State="+state);
}
}
内蕴状态也可认为是类内部变量,而外蕴状态则是从外部传入的参数。
接下来定义一个工厂类,因为客户端不能直接将具体的享元类实例化,而必须通过一个工厂对象,利用一个factory()得到享元对象。当客户端需要单纯的享元对象的时候,需要调用享元工厂factory()方法,并传入所需的内蕴状态,由工厂方法得到所需的享元对象。
public class FlyweightFactory {
private HashMap flies = new HashMap();
private Flyweight fly;
public FlyweightFactory(){
}
//字体样式
public Flyweight factory(Character state){
if(flies.containsKey(state)){
return (Flyweight)flies.get(state);
}else{
fly = new ConcerteFlyweight(state);
flies.put(state, fly);
return fly;
}
}
}
接下来,进行测试下
public class Client {
public static void main(String[] args){
FlyweightFactory factory=new FlyweightFactory();
Flyweight fly=factory.factory(new Character('a'));
fly.operation("罗马字符");
fly.operation("新罗马字符");
fly=factory.factory(new Character('b'));
fly.operation("阿拉伯字符");
}
}
测试结果:
intrinsicState=a,Extrinsic State=罗马字符
intrinsicState=a,Extrinsic State=新罗马字符
intrinsicState=b,Extrinsic State=阿拉伯字符
可以看到字母a共享了一次,即内蕴,字体样式不断改变,即外蕴。
以上是单纯享元,下面看看什么是复合享元。
依然是上面的例子,如果在编辑某段字母是都是同一个样式,这就可以使用复合享元。
还是同样的接口,同样的实现类
public interface Flyweight {
public void operation(String state);
}
public class ConcreteFlyweight implements Flyweight
{
private Character intrinsicState=null;
//构造子,内蕴状态作为参数传入
public ConcreteFlyweight(Character state)
{
this.intrinsicState=state;
}
//外蕴状态作为参数传入方法
public void operation(String state)
{
System.out.println("Intrinsic state="+intrinsicState+",Extrinsic State="+state);
}
}
不同的是,复合享元由单纯享元对象通过复合而成,因此提供了add()这样的聚合管理方法,由于复合享元对象具有不同的聚集元素,这些聚集元素在复合后被创建之后加入,所以这些复合享元对象是不可改变的。复合享元实现接口,并实现operation方法,这个参数对复合享元来说就是外蕴。一个复合享元对象的所有单纯享元对象元素的外蕴状态都是与复合享元对象的外蕴状态相等的,而对象所含有的单纯享元对象的内蕴状态一般不想等。
就编辑器来说,我某一段输入abac,并且都是新罗马字符,从这里理解上面的语句,就是新罗马字符即复合享元的外蕴,与每一个字母的单纯享元的外蕴是一样的,因为他们的样式都是"新罗马".而内蕴却不一定相同,因为,a,b,c是完全不同的字母。这样就理解了。
下面接着看代码:
public class ConcreteCompositeFlyweight implements Flyweight{
private HashMap flies=new HashMap(10);
private Flyweight flyweight;
public ConcreteCompositeFlyweight() { }
//增加一个新的单纯享元对象到聚集中
public void add(Character key,Flyweight fly)
{
flies.put(key,fly);
}
//外蕴状态作为参数传入到方法中
public void operation(String extrinsicState)
{
Flyweight fly=null;
for(Iterator it=flies.entrySet().iterator();it.hasNext();)
{
Map.Entry e=(Map.Entry)it.next();
fly=(Flyweight)e.getValue();
fly.operation(extrinsicState);
}
}
}
接下来看看工厂类,跟单纯享元一样,客户端不能直接调用享元对象,只能通过工厂类。
public class FlyweightFactory
{
private HashMap flies=new HashMap();
public FlyweightFactory() { }
//单纯享元工厂方法,所需状态以参量形式传入
public Flyweight factory(Character state)
{
if(flies.containsKey(state))
{
return (Flyweight)flies.get(state);
} else {
Flyweight fly=new ConcreteFlyweight(state);
flies.put(state,fly);
return fly;
}
}
//符合享元工厂方法,所需状态以参量形式传入,这个参量巧好可以使用string类型
public Flyweight factory(String compositeState)
{
ConcreteCompositeFlyweight compositeFly=new ConcreteCompositeFlyweight();
int length=compositeState.length();
Character state=null;
for(int i=0;i<length;i++)
{
state=new Character(compositeState.charAt(i));
System.out.println("factory("+state+")");
compositeFly.add(state,this.factory(state));
}
return compositeFly;
}
}
这里就是将复合享元对象,分解成若干个单纯享元对象,进行处理。
最后我们测试一下
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
FlyweightFactory factory=new FlyweightFactory();
Flyweight fly=(Flyweight) factory.factory("abac");
fly.operation("罗马字符");
}
}
测试结果:
factory(a)
factory(b)
factory(a)
factory(c)
Intrinsic state=a,Extrinsic State=罗马字符
Intrinsic state=c,Extrinsic State=罗马字符
Intrinsic state=b,Extrinsic State=罗马字符
这就说明了,将复合享元对象差分为若干个单纯享元对象处理,并且外蕴是相同的。
分享到:
相关推荐
首先,我们需要了解享元模式的组成部分: 1. **享元对象(Flyweight)**:这是实际被共享的对象,通常包含一些内部状态(Intrinsic State),这部分状态可以在多个对象之间共享,不会影响对象的共享性。 2. **外部状态...
享元模式的优缺点也值得了解: 优点: - 显著减少对象的数量,节省内存。 - 提高系统的性能,尤其是在对象创建和销毁开销大的情况下。 - 允许系统集中管理大量的细粒度对象,简化对象的管理和使用。 缺点: - 为了...
通过阅读和理解这些代码,我们可以了解到如何在实际项目中应用享元模式,如何定义和使用享元对象,以及如何通过享元工厂来控制对象的创建和复用。 享元模式的优缺点也需要一并了解: 优点: 1. **内存效率高**:...
在阅读《设计模式:可复用面向对象软件的基础》(GOF设计模式)一书时,你会了解到享元模式与其他设计模式的结合使用,如工厂方法模式可以用来创建享元对象,组合模式可以用来处理大量细粒度对象的组织结构。...
它适用于当系统中存在大量细粒度的对象时,享元模式可以将这些对象归类为少数几个共享实例。在C#中,享元模式可以通过缓存技术来实现。 3. **工厂模式**:提供一个创建对象的接口,但让子类决定实例化哪一个类。...
- **享元模式**:运用共享技术有效地支持大量细粒度的对象。 3. 行为型模式(定义对象间交互的模式) - **责任链模式**:避免将请求的发送者和接收者耦合在一起,让多个对象都有可能处理请求,将这些对象连接成一...
结构型模式处理对象组合和类结构,如外观、适配器、代理、装饰、桥接、组合和享元模式,它们优化了类和对象之间的结构关系。行为型模式涉及对象行为和责任分配,包括模板方法、观察者、状态、策略、职责链、命令、...
本篇将深入探讨12种核心的设计模式,它们是:单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式、适配器模式、装饰器模式、代理模式、桥接模式、组合模式、享元模式和观察者模式。 1. **单例模式**:确保一...
2. **享元(FlyWeight)模式**:享元模式用于减少大量相似对象的创建,通过共享已经存在的对象来实现。它主要适用于内存消耗大的场景,例如在图形界面或文本处理中,大量重复的对象可以通过享元模式来优化内存使用。...
结构型模式包括适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式和享元模式。这些模式有助于在不修改原有代码的基础上增加新的功能,或者在不同组件之间建立松散耦合。 1. 适配器模式:将两个不...
包括适配器模式、桥接模式、装饰器模式、外观模式、组合模式、享元模式和代理模式。C#中的接口实现和委托机制为实现这些模式提供了便利。 3. 行为型模式:关注对象之间的职责分配和通信。比如命令模式、解释器模式...
11. **享元模式**:运用共享技术有效支持大量细粒度的对象,减少内存占用。 12. **组合模式**:允许将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 13. **...
2. 结构型模式:这些模式处理对象组合和结构,如适配器模式(Adapter)、桥接模式(Bridge)、组合模式(Composite)、装饰器模式(Decorator)、外观模式(Facade)、享元模式(Flyweight)和代理模式(Proxy)。...
外观模式使子系统更容易被使用,因为它为复杂的子系统提供了一个简单的接口,客户端可以通过这个接口与子系统进行交互,而无需了解子系统的内部实现细节。 在Python和C++这两种不同的编程语言中,外观模式的应用...
结构型模式则涉及如何组合对象和类,如适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式和享元模式。行为型模式关注对象间职责分配和通信,比如策略模式、模板方法模式、观察者模式、责任链模式、...
包括适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式、代理模式等。 行为型模式:通过类之间不同通信方式实现不同行为。包括责任链模式、命名模式、解释器模式、迭代器模式、中介者...
享元模式(Flyweight)通过共享技术,有效地支持大量细粒度的对象。 3. **行为型模式**:行为型模式关注对象之间的责任分配和交互。策略模式(Strategy)定义了一组可以互换的算法,并使它们可以相互替换;模板方法...
适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式和代理模式是结构型模式中的典型代表。 ##### 适配器模式(Adapter) 适配器模式允许不兼容的接口之间进行协作,通过将一个类的接口转换为客户...
总结,灸哥讲解的结构型设计模式涵盖了门面模式、组合模式、装饰器模式、适配器模式和享元模式,这些都是在后端开发中,尤其是在JAVA语言中非常重要的设计模式。理解并灵活运用这些模式,能够帮助开发者编写出更加...