23种设计模式之享元模式

2019-01-12  本文已影响0人  阿跳爱学习

优点:减少内存中对象的数量,相同或相似对象在内存中只存在一个,节省内存,提高系统性能。
缺点:运行时间变长,用时间换取内存。

模式图: image.png
享元模式能做到共享的关键是区分了内部状态和外部状态。
内部状态:可以共享,不会随着环境变化而改变。

外部状态:不可用共享,会随着环境变化而改变。

主要分为四个角色:

例子:比如五子棋中的黑棋或白棋,它们颜色形状都是一样的,可以共享,不会随着环境的变化而改变,这就是内部状态。唯一不一样的就是它们的坐标,不可共享,因为每块棋子的坐标都是不一样的,这就是外部状态。

把外部状态独立出来(UnsharedConcreteFlyweight):

/**
 * 这是一个坐标类。
 * UnsharedConcreteFlyweight: 非共享享元类。不能被共享的子类,可以设计为非共享享元类。
 */

public class CoordinateUnshared {

    private int x, y;

    public CoordinateUnshared(int x, int y) {
        this.x = x;
        this.y = y;
    }

    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;
    }
}

Flyweight: 抽象享元类。一个接口或者抽象类,声明公共方法,这些方法可以向外部提供对象内部状态和设置对象的外部状态:

/**
 * 这是一个棋子抽象享元类
 * Flyweight: 抽象享元类。一个接口或者抽象类,声明公共方法,这些方法可以向外部提供对象内部状态和设置对象的外部状态。
 */

public interface ChessFlyweight {
    void setColor(String color);

    String getColor();

    void displayPosition(CoordinateUnshared c);
}

ConcreteFlyweight: 具体享元类。为内部状态提供成员变量进行存储:

/**
 * 这是一个具体享元类
 * ConcreteFlyweight: 具体享元类。为内部状态提供成员变量进行存储。
 */

public class ChessConcrete implements ChessFlyweight {

    private String color;

    public ChessConcrete(String color) {
        this.color = color;
    }

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

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void displayPosition(CoordinateUnshared c) {
        Log.d("TAG", "对象:" + this + "\n颜色:" + color + "\n棋子位置:" + "x = " + c.getX() + " y = " + c.getY());
    }
}

FlyweightFactory: 享元工厂类:

import java.util.HashMap;
import java.util.Map;

/**
 * FlyweightFactory: 享元工厂类。创建并管理享元对象,享元池一般设置成键值对。
 */

public class ChessFlyweightFactory {

    private static Map<String, ChessFlyweight> map = new HashMap<String, ChessFlyweight>();

    public static ChessFlyweight getChess(String color) {
        if (map.get(color) != null) {
            return map.get(color);
        } else {
            ChessFlyweight chessFlyweight = new ChessConcrete(color);
            map.put(color, chessFlyweight);
            return chessFlyweight;
        }
    }
}

调用:

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

/**
 * 这是调用者
 */

public class MainActivity extends FragmentActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ChessFlyweight chessFlyweight1 = ChessFlyweightFactory.getChess("黑色");
        ChessFlyweight chessFlyweight2 = ChessFlyweightFactory.getChess("黑色");
        ChessFlyweight chessFlyweight3 = ChessFlyweightFactory.getChess("白色");

        Log.d("TAG", "添加外部处理-----------------------");
        chessFlyweight1.displayPosition(new CoordinateUnshared(10, 10));
        chessFlyweight2.displayPosition(new CoordinateUnshared(20, 20));
        chessFlyweight3.displayPosition(new CoordinateUnshared(30, 30));
    }
}
结果: image.png

创建了两次黑色棋子,但是并没有生成新对象,而是同一个对象,只是添加的外部处理不一样(坐标),白色棋子为新对象,因为系统中还不存在白色对象,所以无论创建多少黑色对象和白色对象,黑色和白色也都各只存在一个。
已完成测试!有不对的地方欢迎指出,感恩。

上一篇下一篇

猜你喜欢

热点阅读