CodeGym /జావా బ్లాగ్ /యాదృచ్ఛికంగా /ప్రాక్సీ డిజైన్ నమూనా
John Squirrels
స్థాయి
San Francisco

ప్రాక్సీ డిజైన్ నమూనా

సమూహంలో ప్రచురించబడింది
ప్రోగ్రామింగ్‌లో, మీ అప్లికేషన్ యొక్క నిర్మాణాన్ని సరిగ్గా ప్లాన్ చేయడం ముఖ్యం. డిజైన్ నమూనాలు దీనిని సాధించడానికి ఒక అనివార్య మార్గం. ఈరోజు ప్రాక్సీల గురించి మాట్లాడుకుందాం.

మీకు ప్రాక్సీ ఎందుకు అవసరం?

ఈ నమూనా ఒక వస్తువుకు నియంత్రిత యాక్సెస్‌తో అనుబంధించబడిన సమస్యలను పరిష్కరించడానికి సహాయపడుతుంది. మీరు అడగవచ్చు, "మాకు నియంత్రిత యాక్సెస్ ఎందుకు అవసరం?" ఏది ఏమిటో గుర్తించడంలో మీకు సహాయపడే కొన్ని పరిస్థితులను చూద్దాం.

ఉదాహరణ 1

డేటాబేస్ నుండి నివేదికలను ఎగుమతి చేయడానికి బాధ్యత వహించే తరగతి ఉన్న పాత కోడ్‌తో కూడిన పెద్ద ప్రాజెక్ట్‌ను కలిగి ఉన్నామని ఊహించుకోండి. తరగతి సమకాలీనంగా పనిచేస్తుంది. అంటే, డేటాబేస్ అభ్యర్థనను ప్రాసెస్ చేస్తున్నప్పుడు మొత్తం సిస్టమ్ నిష్క్రియంగా ఉంటుంది. సగటున, నివేదికను రూపొందించడానికి 30 నిమిషాలు పడుతుంది. దీని ప్రకారం, ఎగుమతి ప్రక్రియ 12:30 AMకి ప్రారంభమవుతుంది మరియు నిర్వహణ ఉదయం నివేదికను అందుకుంటుంది. సాధారణ పని వేళల్లో నివేదికను తక్షణమే స్వీకరించడం మంచిదని ఆడిట్ వెల్లడించింది. ప్రారంభ సమయం వాయిదా వేయబడదు మరియు డేటాబేస్ నుండి ప్రతిస్పందన కోసం వేచి ఉన్నప్పుడు సిస్టమ్ నిరోధించదు. సిస్టమ్ ఎలా పనిచేస్తుందో మార్చడం, ప్రత్యేక థ్రెడ్‌లో నివేదికను రూపొందించడం మరియు ఎగుమతి చేయడం దీనికి పరిష్కారం. ఈ పరిష్కారం సిస్టమ్‌ని యధావిధిగా పని చేస్తుంది మరియు నిర్వహణ తాజా నివేదికలను అందుకుంటుంది. అయితే, సమస్య ఉంది: సిస్టమ్ యొక్క ఇతర భాగాలు దాని కార్యాచరణను ఉపయోగిస్తున్నందున ప్రస్తుత కోడ్‌ని తిరిగి వ్రాయడం సాధ్యం కాదు. ఈ సందర్భంలో, మేము ఒక ఇంటర్మీడియట్ ప్రాక్సీ తరగతిని పరిచయం చేయడానికి ప్రాక్సీ నమూనాను ఉపయోగించవచ్చు, అది నివేదికలను ఎగుమతి చేయడానికి, ప్రారంభ సమయాన్ని లాగ్ చేయడానికి మరియు ప్రత్యేక థ్రెడ్‌ని ప్రారంభించడానికి అభ్యర్థనలను అందుకుంటుంది. నివేదిక రూపొందించబడిన తర్వాత, థ్రెడ్ ముగుస్తుంది మరియు అందరూ సంతోషంగా ఉన్నారు.

ఉదాహరణ 2

అభివృద్ధి బృందం ఈవెంట్‌ల వెబ్‌సైట్‌ను సృష్టిస్తోంది. కొత్త ఈవెంట్‌ల డేటాను పొందడానికి, బృందం మూడవ పక్ష సేవను ప్రశ్నిస్తుంది. ఒక ప్రత్యేక ప్రైవేట్ లైబ్రరీ సేవతో పరస్పర చర్యను సులభతరం చేస్తుంది. అభివృద్ధి సమయంలో, ఒక సమస్య కనుగొనబడింది: మూడవ పక్షం సిస్టమ్ దాని డేటాను రోజుకు ఒకసారి అప్‌డేట్ చేస్తుంది, కానీ వినియోగదారు పేజీని రిఫ్రెష్ చేసిన ప్రతిసారీ దానికి అభ్యర్థన పంపబడుతుంది. ఇది పెద్ద సంఖ్యలో అభ్యర్థనలను సృష్టిస్తుంది మరియు సేవ ప్రతిస్పందించడం ఆపివేస్తుంది. సేవ యొక్క ప్రతిస్పందనను కాష్ చేయడం మరియు పేజీలు రీలోడ్ అయినప్పుడు కాష్ చేసిన ఫలితాన్ని సందర్శకులకు అందించడం, కాష్‌ను అవసరమైన విధంగా నవీకరించడం దీనికి పరిష్కారం. ఈ సందర్భంలో, ప్రాక్సీ డిజైన్ నమూనా ఇప్పటికే ఉన్న కార్యాచరణను మార్చని అద్భుతమైన పరిష్కారం.

డిజైన్ నమూనా వెనుక సూత్రం

ఈ నమూనాను అమలు చేయడానికి, మీరు ప్రాక్సీ తరగతిని సృష్టించాలి. ఇది సర్వీస్ క్లాస్ యొక్క ఇంటర్‌ఫేస్‌ను అమలు చేస్తుంది, క్లయింట్ కోడ్ కోసం దాని ప్రవర్తనను అనుకరిస్తుంది. ఈ పద్ధతిలో, క్లయింట్ నిజమైన వస్తువుకు బదులుగా ప్రాక్సీతో పరస్పర చర్య చేస్తాడు. నియమం ప్రకారం, అన్ని అభ్యర్థనలు సేవా తరగతికి పంపబడతాయి, కానీ ముందు లేదా తర్వాత అదనపు చర్యలతో. సరళంగా చెప్పాలంటే, ప్రాక్సీ అనేది క్లయింట్ కోడ్ మరియు లక్ష్య వస్తువు మధ్య ఉండే పొర. పాత మరియు చాలా నెమ్మదైన హార్డ్ డిస్క్ నుండి కాషింగ్ ప్రశ్న ఫలితాలను ఉదాహరణగా పరిగణించండి. లాజిక్‌ను మార్చలేని పురాతన యాప్‌లో ఎలక్ట్రిక్ రైళ్ల టైమ్‌టేబుల్ గురించి మాట్లాడుతున్నామని అనుకుందాం. నవీకరించబడిన టైమ్‌టేబుల్‌తో కూడిన డిస్క్ ప్రతిరోజు నిర్ణీత సమయంలో చొప్పించబడుతుంది. కాబట్టి, మనకు ఉన్నాయి:
  1. TrainTimetableఇంటర్ఫేస్.
  2. ElectricTrainTimetable, ఇది ఈ ఇంటర్‌ఫేస్‌ను అమలు చేస్తుంది.
  3. క్లయింట్ కోడ్ ఈ తరగతి ద్వారా ఫైల్ సిస్టమ్‌తో పరస్పర చర్య చేస్తుంది.
  4. TimetableDisplayక్లయింట్ తరగతి. దీని printTimetable()పద్ధతి తరగతి యొక్క పద్ధతులను ఉపయోగిస్తుంది ElectricTrainTimetable.
రేఖాచిత్రం చాలా సులభం: ప్రాక్సీ డిజైన్ నమూనా: - 2ప్రస్తుతం, printTimetable()పద్ధతి యొక్క ప్రతి కాల్‌తో, ElectricTrainTimetableతరగతి డిస్క్‌ని యాక్సెస్ చేస్తుంది, డేటాను లోడ్ చేస్తుంది మరియు క్లయింట్‌కు అందిస్తుంది. సిస్టమ్ బాగా పనిచేస్తుంది, కానీ ఇది చాలా నెమ్మదిగా ఉంటుంది. ఫలితంగా, కాషింగ్ మెకానిజంను జోడించడం ద్వారా సిస్టమ్ పనితీరును పెంచడానికి నిర్ణయం తీసుకోబడింది. ఇది ప్రాక్సీ నమూనాను ఉపయోగించి చేయవచ్చు: ప్రాక్సీ డిజైన్ నమూనా: - 3అందువల్ల, పాత తరగతికి బదులుగా తరగతితో TimetableDisplayపరస్పర చర్య చేస్తున్నట్లు తరగతి కూడా గమనించదు . ElectricTrainTimetableProxyకొత్త అమలు టైమ్‌టేబుల్‌ను రోజుకు ఒకసారి లోడ్ చేస్తుంది. రిపీట్ రిక్వెస్ట్‌ల కోసం, ఇది మెమరీ నుండి గతంలో లోడ్ చేసిన ఆబ్జెక్ట్‌ను తిరిగి అందిస్తుంది.

ప్రాక్సీకి ఏ పనులు ఉత్తమం?

ఈ నమూనా ఖచ్చితంగా ఉపయోగపడే కొన్ని పరిస్థితులు ఇక్కడ ఉన్నాయి:
  1. కాషింగ్
  2. ఆలస్యం, లేదా సోమరితనం, ప్రారంభించడం మీరు అవసరమైన విధంగా లోడ్ చేయగలిగితే వెంటనే ఆబ్జెక్ట్‌ను ఎందుకు లోడ్ చేయాలి?
  3. లాగిన్ అభ్యర్థనలు
  4. డేటా మరియు యాక్సెస్ యొక్క ఇంటర్మీడియట్ ధృవీకరణ
  5. వర్కర్ థ్రెడ్‌లను ప్రారంభించడం
  6. వస్తువుకు రికార్డింగ్ యాక్సెస్
మరియు ఇతర ఉపయోగ సందర్భాలు కూడా ఉన్నాయి. ఈ నమూనా వెనుక ఉన్న సూత్రాన్ని అర్థం చేసుకోవడం, ఇది విజయవంతంగా వర్తించే పరిస్థితులను మీరు గుర్తించవచ్చు. మొదటి చూపులో, ప్రాక్సీ ముఖభాగం వలె అదే పనిని చేస్తుంది , కానీ అది అలా కాదు. ప్రాక్సీకి సర్వీస్ ఆబ్జెక్ట్‌తో సమానమైన ఇంటర్‌ఫేస్ ఉంటుంది . అలాగే, ఈ నమూనాను డెకరేటర్ లేదా అడాప్టర్ నమూనాలతో కంగారు పెట్టవద్దు . డెకరేటర్ విస్తరించిన ఇంటర్‌ఫేస్‌ను అందిస్తుంది మరియు అడాప్టర్ ప్రత్యామ్నాయ ఇంటర్‌ఫేస్‌ను అందిస్తుంది .

ప్రయోజనాలు మరియు అప్రయోజనాలు

  • + మీరు సర్వీస్ ఆబ్జెక్ట్‌కి యాక్సెస్‌ని మీరు ఎలా కోరుకుంటే అది నియంత్రించవచ్చు
  • + సేవా వస్తువు యొక్క జీవిత చక్రాన్ని నిర్వహించడానికి సంబంధించిన అదనపు సామర్థ్యాలు
  • + ఇది సేవా వస్తువు లేకుండా పనిచేస్తుంది
  • + ఇది పనితీరు మరియు కోడ్ భద్రతను మెరుగుపరుస్తుంది.
  • - అదనపు అభ్యర్థనల కారణంగా పనితీరు మరింత దిగజారిపోయే ప్రమాదం ఉంది
  • - ఇది తరగతి శ్రేణిని మరింత క్లిష్టతరం చేస్తుంది

ఆచరణలో ప్రాక్సీ నమూనా

హార్డ్ డిస్క్ నుండి రైలు టైమ్‌టేబుల్‌లను చదివే వ్యవస్థను అమలు చేద్దాం:

public interface TrainTimetable {
   String[] getTimetable();
   String getTrainDepartureTime();
}
ప్రధాన ఇంటర్‌ఫేస్‌ను అమలు చేసే తరగతి ఇక్కడ ఉంది:

public class ElectricTrainTimetable implements TrainTimetable {

   @Override
   public String[] getTimetable() {
       ArrayList<String> list = new ArrayList<>();
       try {
           Scanner scanner = new Scanner(new FileReader(new File("/tmp/electric_trains.csv")));
           while (scanner.hasNextLine()) {
               String line = scanner.nextLine();
               list.add(line);
           }
       } catch (IOException e) {
           System.err.println("Error:  " + e);
       }
       return list.toArray(new String[list.size()]);
   }

   @Override
   public String getTrainDepartureTime(String trainId) {
       String[] timetable = getTimetable();
       for (int i = 0; i < timetable.length; i++) {
           if (timetable[i].startsWith(trainId+";")) return timetable[i];
       }
       return "";
   }
}
మీరు రైలు టైమ్‌టేబుల్‌ని పొందిన ప్రతిసారీ, ప్రోగ్రామ్ డిస్క్ నుండి ఫైల్‌ను చదువుతుంది. కానీ అది మా కష్టాలకు ప్రారంభం మాత్రమే. మీరు ఒక్క రైలు కోసం టైమ్‌టేబుల్‌ని పొందిన ప్రతిసారీ మొత్తం ఫైల్ చదవబడుతుంది! అటువంటి కోడ్ ఏమి చేయకూడదో ఉదాహరణలలో మాత్రమే ఉండటం మంచిది :) క్లయింట్ తరగతి:

public class TimetableDisplay {
   private TrainTimetable trainTimetable = new ElectricTrainTimetable();

   public void printTimetable() {
       String[] timetable = trainTimetable.getTimetable();
       String[] tmpArr;
       System.out.println("Train\\tFrom\\tTo\\t\\tDeparture time\\tArrival time\\tTravel time");
       for (int i = 0; i < timetable.length; i++) {
           tmpArr = timetable[i].split(";");
           System.out.printf("%s\t%s\t%s\t\t%s\t\t\t\t%s\t\t\t%s\n", tmpArr[0], tmpArr[1], tmpArr[2], tmpArr[3], tmpArr[4], tmpArr[5]);
       }
   }
}
ఉదాహరణ ఫైల్:

9B-6854;London;Prague;13:43;21:15;07:32
BA-1404;Paris;Graz;14:25;21:25;07:00
9B-8710;Prague;Vienna;04:48;08:49;04:01;
9B-8122;Prague;Graz;04:48;08:49;04:01
దీనిని పరీక్షించుదాము:

public static void main(String[] args) {
   TimetableDisplay timetableDisplay = new timetableDisplay();
   timetableDisplay.printTimetable();
}
అవుట్‌పుట్:

Train  From  To  Departure time  Arrival time  Travel time
9B-6854  London  Prague  13:43  21:15  07:32
BA-1404  Paris  Graz  14:25  21:25  07:00
9B-8710  Prague  Vienna  04:48  08:49  04:01
9B-8122  Prague  Graz  04:48  08:49  04:01
ఇప్పుడు మన నమూనాను పరిచయం చేయడానికి అవసరమైన దశల ద్వారా నడుద్దాం:
  1. అసలు ఆబ్జెక్ట్‌కు బదులుగా ప్రాక్సీని ఉపయోగించడానికి అనుమతించే ఇంటర్‌ఫేస్‌ను నిర్వచించండి. మా ఉదాహరణలో, ఇది TrainTimetable.

  2. ప్రాక్సీ తరగతిని సృష్టించండి. ఇది సేవా వస్తువుకు సూచనను కలిగి ఉండాలి (తరగతిలో దీన్ని సృష్టించండి లేదా కన్స్ట్రక్టర్‌కు పాస్ చేయండి).

    మా ప్రాక్సీ తరగతి ఇక్కడ ఉంది:

    
    public class ElectricTrainTimetableProxy implements TrainTimetable {
       // Reference to the original object
       private TrainTimetable trainTimetable = new ElectricTrainTimetable();
      
       private String[] timetableCache = null
    
       @Override
       public String[] getTimetable() {
           return trainTimetable.getTimetable();
       }
    
       @Override
       public String getTrainDepartureTime(String trainId) {
           return trainTimetable.getTrainDepartureTime(trainId);
       }
      
       public void clearCache() {
           trainTimetable = null;
       }
    }
    

    ఈ దశలో, మేము అసలు ఆబ్జెక్ట్‌కు సూచనతో తరగతిని సృష్టిస్తాము మరియు అన్ని కాల్‌లను దానికి ఫార్వార్డ్ చేస్తున్నాము.

  3. ప్రాక్సీ క్లాస్ యొక్క లాజిక్‌ను అమలు చేద్దాం. ప్రాథమికంగా, కాల్‌లు ఎల్లప్పుడూ అసలు వస్తువుకు మళ్లించబడతాయి.

    
    public class ElectricTrainTimetableProxy implements TrainTimetable {
       // Reference to the original object
       private TrainTimetable trainTimetable = new ElectricTrainTimetable();
    
       private String[] timetableCache = null
    
       @Override
       public String[] getTimetable() {
           if (timetableCache == null) {
               timetableCache = trainTimetable.getTimetable();
           }
           return timetableCache;
       }
    
       @Override
       public String getTrainDepartureTime(String trainId) {
           if (timetableCache == null) {
               timetableCache = trainTimetable.getTimetable();
           }
           for (int i = 0; i < timetableCache.length; i++) {
               if (timetableCache[i].startsWith(trainId+";")) return timetableCache[i];
           }
           return "";
       }
    
       public void clearCache() {
           trainTimetable = null;
       }
    }
    

    getTimetable()టైమ్‌టేబుల్ శ్రేణి మెమరీలో కాష్ చేయబడిందో లేదో తనిఖీ చేస్తుంది . కాకపోతే, ఇది డిస్క్ నుండి డేటాను లోడ్ చేయమని అభ్యర్థనను పంపుతుంది మరియు ఫలితాన్ని సేవ్ చేస్తుంది. టైమ్‌టేబుల్ ఇప్పటికే అభ్యర్థించబడి ఉంటే, అది త్వరగా ఆబ్జెక్ట్‌ను మెమరీ నుండి తిరిగి ఇస్తుంది.

    దాని సాధారణ కార్యాచరణకు ధన్యవాదాలు, getTrainDepartureTime() పద్ధతిని అసలు ఆబ్జెక్ట్‌కి మళ్లించాల్సిన అవసరం లేదు. మేము దాని కార్యాచరణను కొత్త పద్ధతిలో నకిలీ చేసాము.

    ఇది చేయవద్దు. మీరు కోడ్‌ను డూప్లికేట్ చేయవలసి వస్తే లేదా అలాంటిదే ఏదైనా చేయవలసి వస్తే, అప్పుడు ఏదో తప్పు జరిగింది మరియు మీరు సమస్యను వేరే కోణం నుండి మళ్లీ చూడాలి. మా సాధారణ ఉదాహరణలో, మాకు వేరే ఎంపిక లేదు. కానీ నిజమైన ప్రాజెక్ట్‌లలో, కోడ్ చాలావరకు సరిగ్గా వ్రాయబడుతుంది.

  4. క్లయింట్ కోడ్‌లో, అసలు ఆబ్జెక్ట్‌కు బదులుగా ప్రాక్సీ ఆబ్జెక్ట్‌ను సృష్టించండి:

    
    public class TimetableDisplay {
       // Changed reference
       private TrainTimetable trainTimetable = new ElectricTrainTimetableProxy();
    
       public void printTimetable() {
           String[] timetable = trainTimetable.getTimetable();
           String[] tmpArr;
           System.out.println("Train\\tFrom\\tTo\\t\\tDeparture time\\tArrival time\\tTravel time");
           for (int i = 0; i < timetable.length; i++) {
               tmpArr = timetable[i].split(";");
               System.out.printf("%s\t%s\t%s\t\t%s\t\t\t\t%s\t\t\t%s\n", tmpArr[0], tmpArr[1], tmpArr[2], tmpArr[3], tmpArr[4], tmpArr[5]);
           }
       }
    }
    

    తనిఖీ

    
    Train  From  To  Departure time  Arrival time  Travel time
    9B-6854  London  Prague  13:43  21:15  07:32
    BA-1404  Paris  Graz  14:25  21:25  07:00
    9B-8710  Prague  Vienna  04:48  08:49  04:01
    9B-8122  Prague  Graz  04:48  08:49  04:01
    

    గ్రేట్, ఇది సరిగ్గా పనిచేస్తుంది.

    మీరు కొన్ని షరతులపై ఆధారపడి అసలు వస్తువు మరియు ప్రాక్సీ వస్తువు రెండింటినీ సృష్టించే ఫ్యాక్టరీ ఎంపికను కూడా పరిగణించవచ్చు.

మేము వీడ్కోలు చెప్పే ముందు, ఇక్కడ ఉపయోగకరమైన లింక్ ఉంది

నేటికీ అంతే! పాఠాలకు తిరిగి రావడం మరియు ఆచరణలో మీ కొత్త జ్ఞానాన్ని ప్రయత్నించడం చెడ్డ ఆలోచన కాదు :)
వ్యాఖ్యలు
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION