7.7享元模式
7.7.1概念
? 享元模式是通過共享對(duì)象減少內(nèi)存使用,來提高程序性能。在此模式中,分為內(nèi)部狀態(tài)和外部狀態(tài),其中相似的對(duì)象被存儲(chǔ)在享元對(duì)象內(nèi)部,并對(duì)于所有享元對(duì)象都是相同的,且狀態(tài)通常是不變的。只在需要時(shí)內(nèi)部共享,而不是每次創(chuàng)建新的對(duì)象。而外部狀態(tài)是享元對(duì)象依賴的,可能變化的部分。這部分狀態(tài)不存儲(chǔ)在享元對(duì)象內(nèi)部,而是在使用享元對(duì)象時(shí)傳遞給對(duì)象。
7.7.2場(chǎng)景
? 在棋類游戲中,棋子可以看作是享元對(duì)象,因?yàn)槠遄优c棋子之間有著相同的屬性和方法,例如在顏色、大小、移動(dòng)規(guī)則上都有著相同的特質(zhì)。因此在棋類游戲中,可以使用享元模式來共享相同的棋子對(duì)象,避免創(chuàng)建大量的棋子對(duì)象,從而提高游戲性能。
7.7.3優(yōu)勢(shì) / 劣勢(shì)
- 減少內(nèi)存消耗:通過共享公共狀態(tài),減少創(chuàng)建對(duì)象的數(shù)量
- 提升性能:通過共享對(duì)象來減少內(nèi)存中對(duì)象的數(shù)量,可以減少垃圾回收的頻率
- 線程安全問題:享元模式的對(duì)象可能會(huì)導(dǎo)致線程安全問題,需要采取一定的措施
- 適用場(chǎng)景有限:享元模式存在大量相似對(duì)象的場(chǎng)景,若不適用,則會(huì)導(dǎo)致性能下降,代碼復(fù)雜度增加
7.7.4享元模式可分為
- 享元接口Flyweight:所有具體享元類的共享接口,通常包含對(duì)外部狀態(tài)的操作
- 具體享元類ConcreteFlyweight:繼承Flyweight類或?qū)崿F(xiàn)享元接口,包含內(nèi)部狀態(tài)
- 享元工廠類FlyweightFactory:創(chuàng)建并管理享元對(duì)象,當(dāng)用戶請(qǐng)求時(shí),提供已創(chuàng)建的實(shí)例或者創(chuàng)建一個(gè)
- 客戶端Client:維護(hù)外部狀態(tài),在使用享元對(duì)象時(shí),將外部狀態(tài)傳遞給享元對(duì)象
7.7.5享元模式
package com.technologystatck.designpattern.mode.flyweight;
import java.util.HashMap;
import java.util.Map;
public class Flyweight {
public static void main(String[] args) {
//實(shí)例化享元工廠對(duì)象
FlyweightFactory factory = new FlyweightFactory();
//獲取或創(chuàng)建享元對(duì)象,并傳遞外部狀態(tài)
Flyweights flyweightA = factory.getFlyweight("A");
flyweightA.operation("External State A");
Flyweights flyweightB = factory.getFlyweight("B");
flyweightB.operation("External State B");
Flyweights flyweightC = factory.getFlyweight("A");
flyweightC.operation("External State C");
}
}
//創(chuàng)建享元接口
interface Flyweights {
//操作外部狀態(tài)
void operation(String extrinsicState);
}
//實(shí)現(xiàn)具體享元類,存儲(chǔ)內(nèi)部狀態(tài)
class ConcreteFlyweight implements Flyweights{
//內(nèi)部狀態(tài)
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("Intrinsic State: "+intrinsicState+",External State: "+extrinsicState);
}
}
//創(chuàng)建享元工廠類,創(chuàng)建并管理Flyweight對(duì)象,
//當(dāng)用戶請(qǐng)求一個(gè)Flyweight時(shí),享元工廠會(huì)提供一個(gè)已經(jīng)創(chuàng)建的實(shí)例或創(chuàng)建一個(gè)
class FlyweightFactory{
private Map<String,Flyweights> flyweights=new HashMap<>();
public Flyweights getFlyweight(String key){
//若沒有享元對(duì)象時(shí),就將傳進(jìn)來的key值創(chuàng)建一個(gè)
if(!flyweights.containsKey(key)){
flyweights.put(key,new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
}
7.7.6實(shí)戰(zhàn)
7.7.6.1題目描述
? 在一個(gè)圖形編輯器中,用戶可以繪制不同類型的圖形,包括圓形(CIRCLE)、矩形(RECTANGLE)、三角形(TRIANGLE)等。現(xiàn)在,請(qǐng)你實(shí)現(xiàn)一個(gè)圖形繪制程序,要求能夠共享相同類型的圖形對(duì)象,以減少內(nèi)存占用。
7.7.6.2輸入描述
輸入包含多行,每行表示一個(gè)繪制命令。每個(gè)命令包括兩部分:
圖形類型(Circle、Rectangle 或 Triangle)
繪制的坐標(biāo)位置(兩個(gè)整數(shù),分別表示 x 和 y)文章來源:http://www.zghlxwxcb.cn/news/detail-816480.html
7.7.6.3輸出描述
對(duì)于每個(gè)繪制命令,輸出相應(yīng)圖形被繪制的位置信息。如果圖形是首次繪制,輸出 “drawn at”,否則輸出 “shared at”。文章來源地址http://www.zghlxwxcb.cn/news/detail-816480.html
7.7.6.4代碼
package com.technologystatck.designpattern.mode.flyweight;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//創(chuàng)建工廠實(shí)例
GraphicFactory graphicFactory = new GraphicFactory();
while(scanner.hasNext()){
String command = scanner.nextLine();
//定義一個(gè)靜態(tài)方法
proessCommand(graphicFactory,command);
}
}
public static void proessCommand(GraphicFactory graphicFactory,String command){
//定義數(shù)組存放類型變量
String[] parts = command.split(" ");
DrawType drawType=DrawType.valueOf(parts[0]);
int x=Integer.parseInt(parts[1]);
int y=Integer.parseInt(parts[2]);
//
Graphic graphic=graphicFactory.getGraphic(drawType);
graphic.draw(new ConcretePosition(x,y));
((ConcreteGraphic) graphic).setFirstTime(false);
}
}
//使用枚舉創(chuàng)建圖形類型
enum DrawType{
CIRCLE,RECTANGLE,TRIANGLE;
}
//創(chuàng)建坐標(biāo)類
class ConcretePosition{
//內(nèi)部狀態(tài)
private int x;
private int y;
public ConcretePosition() {
}
public ConcretePosition(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;
}
}
//創(chuàng)建圖像享元接口
interface Graphic{
//外部狀態(tài)
void draw(ConcretePosition concretePosition);
}
//創(chuàng)建具體圖形實(shí)現(xiàn)類
class ConcreteGraphic implements Graphic{
//內(nèi)部狀態(tài)
private DrawType drawType;
public ConcreteGraphic(DrawType drawType) {
this.drawType = drawType;
}
//檢查是否是第一次繪制該圖形
private Boolean isFirstTime=true;
public Boolean getFirstTime() {
return isFirstTime;
}
public void setFirstTime(Boolean firstTime) {
isFirstTime = firstTime;
}
//描繪圖形方法
@Override
public void draw(ConcretePosition concretePosition) {
System.out.println(drawType+(isFirstTime ? "drawn":"shared")+" at ("+
concretePosition.getX()+" , "+concretePosition.getY()+")");
}
}
//創(chuàng)建享元圖形工廠
class GraphicFactory{
private Map<DrawType,Graphic> graphicEditors=new HashMap<>();
//檢查是否已創(chuàng)建對(duì)象
public Graphic getGraphic(DrawType drawType){
//若時(shí)第一次創(chuàng)建,就實(shí)例化一個(gè)新對(duì)象,否則就返回已經(jīng)創(chuàng)建的對(duì)象。
if(!graphicEditors.containsKey(drawType)){
graphicEditors.put(drawType,new ConcreteGraphic(drawType));
}
return graphicEditors.get(drawType);
}
}
8.1.7總結(jié)
-
享元模式
- 優(yōu)點(diǎn):通過減少創(chuàng)建對(duì)象的數(shù)量以此來減少內(nèi)存消耗,提高程序的性能
- 總結(jié):分為外部狀態(tài)和內(nèi)部狀態(tài),內(nèi)部狀態(tài)主要是大量相似的對(duì)象,外部狀態(tài)是變化較大的對(duì)象
- 場(chǎng)景:用于包含大量相似對(duì)象,且對(duì)象的內(nèi)部狀態(tài)可以共享,外部狀態(tài)變化較大時(shí)
到了這里,關(guān)于笨蛋學(xué)設(shè)計(jì)模式結(jié)構(gòu)型模式-享元模式【13】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!