"హలో, మిత్రమా!"
"హాయ్, బిలాబో!"
"మాకు ఇంకా కొంత సమయం మిగిలి ఉంది, కాబట్టి నేను మీకు మరో మూడు నమూనాల గురించి చెబుతాను."
"ఇంకా ముగ్గురా? మొత్తం ఎన్ని ఉన్నాయి?"
"ప్రస్తుతం డజన్ల కొద్దీ ప్రసిద్ధ నమూనాలు ఉన్నాయి, కానీ "విజయవంతమైన పరిష్కారాల" సంఖ్య అపరిమితంగా ఉంది."
"నేను చూస్తున్నాను. కాబట్టి నేను అనేక డజన్ల నమూనాలను నేర్చుకోవాలి?"
"మీకు నిజమైన ప్రోగ్రామింగ్ అనుభవం ఉన్నంత వరకు, వారు మీకు ఎక్కువ ఇవ్వరు."
"మీరు కొంచెం ఎక్కువ అనుభవాన్ని పొందడం మంచిది, ఆపై, ఒక సంవత్సరంలో, ఈ అంశానికి తిరిగి వెళ్లి, వాటిని మరింత లోతుగా అర్థం చేసుకోవడానికి ప్రయత్నించండి. అత్యంత ప్రజాదరణ పొందిన డిజైన్ నమూనాలలో కనీసం రెండు డజన్ల కొద్దీ."
"ఒకరి అనుభవాన్ని ఉపయోగించకుండా మరియు బదులుగా 110 వ సారి ఏదైనా కనిపెట్టడం పాపం."
"నేను అంగీకరిస్తాను."
"అప్పుడు ప్రారంభిద్దాం."
అడాప్టర్ (లేదా రేపర్) నమూనా
"మీరు చైనాకు వచ్చి, ఎలక్ట్రికల్ అవుట్లెట్లు వేరొక ప్రమాణాన్ని అనుసరిస్తాయని ఊహించుకోండి. రంధ్రాలు గుండ్రంగా ఉండవు, ఫ్లాట్గా ఉంటాయి. ఈ సందర్భంలో, మీకు అడాప్టర్ అవసరం."
"ప్రోగ్రామింగ్లో కూడా ఇలాంటిదే ఏదైనా జరగవచ్చు. తరగతులు సారూప్యమైన కానీ భిన్నమైన ఇంటర్ఫేస్లపై పనిచేస్తాయి. కాబట్టి మనం వాటి మధ్య అడాప్టర్ను తయారు చేయాలి."
"ఇది ఇలా కనిపిస్తుంది:"
interface Time
{
int getSeconds();
int getMinutes();
int getHours();
}
interface TotalTime
{
int getTotalSeconds();
}
"మనకు రెండు ఇంటర్ఫేస్లు ఉన్నాయని అనుకుందాం: సమయం మరియు టోటల్ టైమ్ ."
" GetSeconds (), getMinutes () మరియు getHours () పద్ధతులను ఉపయోగించి ప్రస్తుత సమయాన్ని పొందడానికి టైమ్ ఇంటర్ఫేస్ మిమ్మల్ని అనుమతిస్తుంది ."
" టోటల్ టైమ్ ఇంటర్ఫేస్ అర్ధరాత్రి నుండి ప్రస్తుత క్షణం వరకు గడిచిన సెకన్ల సంఖ్యను పొందడానికి మిమ్మల్ని అనుమతిస్తుంది."
"మనకు టోటల్టైమ్ ఆబ్జెక్ట్ ఉంటే మనం ఏమి చేయాలి , కానీ మనకు టైమ్ ఆబ్జెక్ట్ కావాలా లేదా వైస్ వెర్సా?"
"దీని కోసం మేము అడాప్టర్ తరగతులను వ్రాయవచ్చు. ఉదాహరణకు:"
class TotalTimeAdapter implements Time
{
private TotalTime totalTime;
public TotalTimeAdapter(TotalTime totalTime)
{
this.totalTime = totalTime;
}
int getSeconds()
{
return totalTime.getTotalSeconds() % 60; // seconds
}
int getMinutes()
{
return totalTime.getTotalSeconds() / 60; // minutes
}
int getHours()
{
return totalTime.getTotalSeconds() / (60 * 60); // hours
}
}
TotalTime totalTime = TimeManager.getCurrentTime();
Time time = new TotalTimeAdapter(totalTime);
System.out.println(time.getHours() + " : " + time.getMinutes () + " : " +time.getSeconds());
"మరియు ఇతర దిశలో ఒక అడాప్టర్:"
class TimeAdapter implements TotalTime
{
private Time time;
public TimeAdapter(Time time)
{
this.time = time;
}
int getTotalSeconds()
{
return time.getHours() * 60 * 60 + time.getMinutes() * 60 + time.getSeconds();
}
}
Time time = new Time();
TotalTime totalTime = new TimeAdapter(time);
System.out.println(time.getTotalSeconds());
"ఆహ్. నాకిష్టం. అయితే ఉదాహరణలు ఏమైనా ఉన్నాయా?"
"అయితే! ఉదాహరణగా, InputStreamReader ఒక క్లాసిక్ అడాప్టర్. ఇది InputStreamని రీడర్గా మారుస్తుంది."
"కొన్నిసార్లు ఈ నమూనాను రేపర్ అని కూడా పిలుస్తారు, ఎందుకంటే కొత్త తరగతి మరొక వస్తువును చుట్టేస్తుంది."
"మీరు ఇక్కడ కొన్ని ఇతర ఆసక్తికరమైన విషయాలు చదువుకోవచ్చు ."
ప్రాక్సీ నమూనా
"ప్రాక్సీ నమూనా కొంతవరకు రేపర్ నమూనాతో సమానంగా ఉంటుంది. అయితే దీని ఉద్దేశ్యం ఇంటర్ఫేస్లను మార్చడం కాదు, ప్రాక్సీ తరగతి లోపల నిల్వ చేయబడిన అసలు వస్తువుకు ప్రాప్యతను నియంత్రించడం. అంతేకాకుండా, అసలు తరగతి మరియు ప్రాక్సీ రెండూ సాధారణంగా ఒకే ఇంటర్ఫేస్ను కలిగి ఉంటాయి, ఇది ప్రాక్సీ ఆబ్జెక్ట్తో ఒరిజినల్ క్లాస్ యొక్క వస్తువును భర్తీ చేయడం సులభం చేస్తుంది."
"ఉదాహరణకి:"
interface Bank
{
public void setUserMoney(User user, double money);
public int getUserMoney(User user);
}
class CitiBank implements Bank
{
public void setUserMoney(User user, double money)
{
UserDAO.updateMoney(user, money);
}
public int getUserMoney(User user)
{
return UserDAO.getMoney(user);
}
}
class BankSecurityProxy implements Bank
{
private Bank bank;
public BankSecurityProxy(Bank bank)
{
this.bank = bank;
}
public void setUserMoney(User user, double money)
{
if (!SecurityManager.authorize(user, BankAccounts.Manager))
throw new SecurityException("User can’t change money value");
bank.setUserMoney(user, money);
}
public int getUserMoney(User user)
{
if (!SecurityManager.authorize(user, BankAccounts.Manager))
throw new SecurityException("User can’t get money value");
return bank.getUserMoney(user);
}
}
"పై ఉదాహరణలో, మేము బ్యాంక్ ఇంటర్ఫేస్ మరియు సిటీబ్యాంక్ క్లాస్ గురించి వివరించాము, ఈ ఇంటర్ఫేస్ అమలు."
"ఇంటర్ఫేస్ వినియోగదారు ఖాతా బ్యాలెన్స్ని పొందడానికి లేదా మార్చడానికి మిమ్మల్ని అనుమతిస్తుంది."
ఆపై మేము BankSecurityProxyని సృష్టించాము , ఇది బ్యాంక్ ఇంటర్ఫేస్ను కూడా అమలు చేస్తుంది మరియు వేరే బ్యాంక్ ఇంటర్ఫేస్కు సూచనను నిల్వ చేస్తుంది. ఈ తరగతి యొక్క పద్ధతులు వినియోగదారు ఖాతా యజమాని లేదా బ్యాంక్ మేనేజర్ కాదా అని తనిఖీ చేస్తాయి. అది కాకపోతే, సెక్యూరిటీ మినహాయింపు విసిరివేయబడుతుంది."
"ఇది ఆచరణలో ఎలా పని చేస్తుందో ఇక్కడ ఉంది:"
User user = AuthManager.authorize(login, password);
Bank bank = BankFactory.createUserBank(user);
bank.setUserMoney(user, 1000000);
User user = AuthManager.authorize(login, password);
Bank bank = BankFactory.createUserBank(user);
bank = new BankSecurityProxy(bank);
bank.setUserMoney(user, 1000000);
"మొదటి ఉదాహరణలో, మేము బ్యాంక్ ఆబ్జెక్ట్ను సృష్టించాము మరియు దాని సెట్యూజర్మనీ పద్ధతిని పిలుస్తాము.
"రెండవ ఉదాహరణలో, మేము అసలు బ్యాంక్ ఆబ్జెక్ట్ను BankSecurityProxy ఆబ్జెక్ట్లో చుట్టాము. అవి ఒకే ఇంటర్ఫేస్ను కలిగి ఉంటాయి, కాబట్టి తదుపరి కోడ్ పని చేస్తూనే ఉంటుంది. కానీ ఇప్పుడు ఒక పద్ధతిని పిలిచిన ప్రతిసారి భద్రతా తనిఖీ చేయబడుతుంది."
"కూల్!"
అవును ."
"ఇంకేముంది... ఈ వస్తువుల గొలుసులన్నింటినీ సృష్టించడం బ్యాంక్ఫ్యాక్టరీ తరగతిలో ఉంచబడుతుంది , ఇక్కడ మీరు మీకు అవసరమైన వాటిని ప్రారంభించవచ్చు/నిలిపివేయవచ్చు."
" బఫర్డ్ రీడర్ ఇదే సూత్రాన్ని ఉపయోగించి పని చేస్తుంది. ఇది రీడర్ , కానీ ఇది అదనపు పని చేస్తుంది."
"ఈ విధానం వివిధ "ముక్కలు" నుండి అవసరమైన కార్యాచరణతో ఒక వస్తువును "సమీకరించడానికి" మిమ్మల్ని అనుమతిస్తుంది."
"ఓహ్, నేను దాదాపు మర్చిపోయాను. నేను మీకు చూపిన దానికంటే ప్రాక్సీలు చాలా విస్తృతంగా ఉపయోగించబడుతున్నాయి. మీరు ఇతర ఉపయోగాల గురించి ఇక్కడ చదవవచ్చు ."
వంతెన నమూనా
"కొన్నిసార్లు ప్రోగ్రామ్ నడుస్తున్నప్పుడు ఆబ్జెక్ట్ యొక్క కార్యాచరణను గణనీయంగా మార్చడం అవసరం. ఉదాహరణకు, మీరు ఒక గాడిద పాత్రతో గేమ్ను కలిగి ఉన్నారని అనుకుందాం, అది ఒక మంత్రగాడి ద్వారా డ్రాగన్గా మారింది. డ్రాగన్ పూర్తిగా భిన్నమైన ప్రవర్తన మరియు లక్షణాలను కలిగి ఉంది, కానీ అది అదే వస్తువు!"
"మనం ఒక కొత్త వస్తువును సృష్టించి, దానితో పూర్తి చేయలేమా?"
"ఎల్లప్పుడూ కాదు. మీ గాడిద కొన్ని పాత్రలతో స్నేహంగా ఉందనుకోండి, లేదా బహుశా అది అనేక మంత్రాల ప్రభావంతో ఉండవచ్చు లేదా కొన్ని అన్వేషణలలో పాలుపంచుకుంది. మరో మాటలో చెప్పాలంటే, వస్తువు ఇప్పటికే చాలా ప్రదేశాలలో వాడుకలో ఉండవచ్చు - మరియు చాలా ఇతర వస్తువులకు లింక్ చేయబడింది. కాబట్టి ఈ సందర్భంలో, కొత్త వస్తువును సృష్టించడం అనేది ఒక ఎంపిక కాదు."
"సరే, అప్పుడు ఏమి చేయవచ్చు?"
"వంతెన నమూనా అత్యంత విజయవంతమైన పరిష్కారాలలో ఒకటి."
"ఈ నమూనా ఒక వస్తువును రెండు వస్తువులుగా విభజిస్తుంది: "ఇంటర్ఫేస్ ఆబ్జెక్ట్" మరియు "ఇంప్లిమెంటేషన్ ఆబ్జెక్ట్"."
"ఇంటర్ఫేస్ మరియు దానిని అమలు చేసే తరగతి మధ్య తేడా ఏమిటి?"
"ఇంటర్ఫేస్ మరియు క్లాస్తో, మేము ఒక వస్తువుతో ముగించాము. కానీ ఇక్కడ — మనకు రెండు ఉన్నాయి. ఈ ఉదాహరణ చూడండి:"
class User
{
private UserImpl realUser;
public User(UserImpl impl)
{
realUser = impl;
}
public void run() //Run
{
realUser.run();
}
public void fly() //Fly
{
realUser.fly();
}
}
class UserImpl
{
public void run()
{
}
public void fly()
{
}
}
"ఆపై మీరు UserImpl యొక్క అనేక ఉపవర్గాలను ప్రకటించవచ్చు, ఉదాహరణకు UserDonkey (గాడిద) మరియు UserDragon (డ్రాగన్)."
"అదే, ఇది ఎలా పని చేస్తుందో నాకు నిజంగా అర్థం కాలేదు."
"సరే, ఇలాంటివి:"
class User
{
private UserImpl realUser;
public User(UserImpl impl)
{
realUser = impl;
}
public void transformToDonkey()
{
realUser = new UserDonkeyImpl();
}
public void transformToDragon()
{
realUser = new UserDragonImpl();
}
}
User user = new User(new UserDonkey()); // Internally, we're a donkey
user.transformToDragon(); // Now we're a dragon internally
"కాబట్టి ఇది ప్రాక్సీ లాంటిది."
"అవును, కానీ ప్రాక్సీలో ప్రధాన వస్తువు ఎక్కడో విడిగా నిల్వ చేయబడుతుంది మరియు కోడ్ బదులుగా ప్రాక్సీలతో పని చేస్తుంది. ఇక్కడ అందరూ ప్రధాన వస్తువుతో పనిచేస్తారని మేము చెబుతున్నాము, కానీ దాని భాగాలు అంతర్గతంగా మారుతాయి."
"ఆహ్. థాంక్స్. దాని గురించి మరింత చదవడానికి మీరు నాకు లింక్ ఇస్తారా?"
"అయితే, అమిగో, నా స్నేహితుడు. ఇదిగో: వంతెన నమూనా ."
GO TO FULL VERSION