Programování

Návrh se statickými prvky

Ačkoli je Java do značné míry objektově orientovaná, není to čistý objektově orientovaný jazyk. Jedním z důvodů, proč Java není čistě objektově orientovaná, je to, že ne všechno v ní je objekt. Například Java umožňuje deklarovat proměnné primitivních typů (int, plovák, booleovskýatd.), které nejsou objekty. A Java má statická pole a metody, které jsou nezávislé a oddělené od objektů. Tento článek poskytuje rady, jak používat statická pole a metody v programu Java při zachování objektově zaměřeného zaměření ve vašich návrzích.

Životnost třídy ve virtuálním stroji Java (JVM) má mnoho podobností s životností objektu. Stejně jako může mít objekt stav, představovaný hodnotami jeho proměnných instance, může mít třída stav, představovaný hodnotami jeho proměnných třídy. Stejně jako JVM nastavuje proměnné instance na výchozí počáteční hodnoty před provedením inicializačního kódu, JVM nastaví proměnné třídy na výchozí počáteční hodnoty před provedením inicializačního kódu. A stejně jako objekty, mohou být třídy uvolňovány, pokud již nejsou spuštěnou aplikací odkazovány.

Mezi třídami a objekty však existují významné rozdíly. Snad nejdůležitějším rozdílem je způsob, jakým jsou vyvolány metody instance a třídy: metody instance jsou (z větší části) dynamicky vázány, ale metody třídy jsou vázány staticky. (Ve třech zvláštních případech nejsou metody instance dynamicky vázány: vyvolání metod soukromé instance, vyvolání inic metody (konstruktory) a vyvolání pomocí super klíčové slovo. Další informace najdete v části Zdroje.)

Dalším rozdílem mezi třídami a objekty je stupeň skrývání dat poskytovaný úrovněmi soukromého přístupu. Pokud je proměnná instance deklarována jako soukromá, mají k ní přístup pouze metody instance. To vám umožní zajistit integritu dat instance a zajistit objekty bezpečné pro vlákna. Zbytek programu nemůže přímo přistupovat k těmto proměnným instance, ale musí projít metodami instance, aby manipuloval s proměnnými instance. Ve snaze, aby se třída chovala jako dobře navržený objekt, můžete proměnné třídy nastavit jako soukromé a definovat metody třídy, které s nimi manipulují. Tímto způsobem však nedostanete tak dobrou záruku bezpečnosti vláken nebo dokonce integrity dat, protože určitý druh kódu má speciální oprávnění, které jim poskytuje přímý přístup k proměnným soukromé třídy: metodám instance a dokonce i inicializátorům instance proměnné, může k těmto proměnným soukromé třídy přistupovat přímo.

Takže statická pole a metody tříd, i když jsou v mnoha ohledech podobné polím instance a metodám objektů, mají významné rozdíly, které by měly ovlivnit způsob, jakým je používáte v návrzích.

Zacházení s třídami jako s objekty

Při navrhování programů Java se pravděpodobně setkáte s mnoha situacemi, ve kterých cítíte potřebu objektu, který funguje nějakým způsobem jako třída. Můžete například chtít objekt, jehož životnost odpovídá životnosti třídy. Nebo můžete chtít objekt, který se stejně jako třída omezuje na jediný instance v prostoru pro křestní jména.

V návrhových situacích, jako jsou tyto, může být lákavé vytvořit třídu a použít ji jako objekt, aby bylo možné definovat proměnné třídy, učinit je soukromými a definovat některé metody veřejné třídy, které manipulují s proměnnými třídy. Stejně jako objekt má taková třída stav. Stejně jako dobře navržený objekt jsou proměnné, které definují stav, soukromé a vnější svět může tento stav ovlivnit pouze vyvoláním metod třídy.

Bohužel s tímto přístupem „třída jako objekt“ existují určité problémy. Protože metody třídy jsou staticky vázané, vaše třída jako objekt nebude využívat výhody flexibility polymorfismu a upcastingu. (Definice polymorfismu a dynamické vazby najdete v článku Design Techniques, Složení versus dědičnost.) Polymorfismus je umožněn a upcasting užitečný díky dynamické vazbě, ale metody třídy nejsou dynamicky vázány. Pokud někdo podtřídí vaši třídu jako objekt, nebude to moci přepsat vaše metody třídy deklarováním metod třídy se stejným názvem; budou moci jen skrýt jim. Když je vyvolána jedna z těchto předefinovaných metod tříd, JVM vybere implementaci metody tak, aby se nespouštěla ​​třídou objektu za běhu, ale typem proměnné v době kompilace.

Kromě toho je bezpečnost podprocesu a integrita dat dosažená pečlivou implementací metod třídy ve vaší třídě jako objekt jako dům postavený ze slámy. Vaše bezpečnost vlákna a integrita dat budou zaručeny, pokud všichni používají metody třídy k manipulaci se stavem uloženým v proměnných třídy. Ale neopatrný nebo bezradný programátor by mohl, s přidáním jedné instance metody, která přistupuje přímo k vašim proměnným soukromé třídy, nechtěně nafouknout a nafouknout a vyhodit bezpečnost vlákna a integritu dat.

Z tohoto důvodu je mým hlavním vodítkem týkajícím se třídních proměnných a třídních metod:

Nezacházejte s třídami jako s objekty.

Jinými slovy, nenavrhujte se statickými poli a metodami třídy, jako by šlo o pole instance a metody objektu.

Pokud chcete nějaký stav a chování, jehož životnost odpovídá životnosti třídy, vyhněte se simulaci objektu pomocí proměnných třídy a metod třídy. Místo toho vytvořte skutečný objekt a pomocí proměnné třídy podržte odkaz na něj a metody třídy poskytněte přístup k odkazu na objekt. Pokud chcete zajistit, aby v jednom prostoru jmen existovala pouze jedna instance určitého stavu a chování, nezkoušejte navrhnout třídu, která simuluje objekt. Místo toho vytvořte a jedináček - objekt zaručeně obsahuje pouze jednu instanci na jmenný prostor.

K čemu jsou tedy členové třídy dobré?

Podle mého názoru je nejlepším přístupem ke kultivaci při navrhování programů Java myslet na objekty, objekty, objekty. Zaměřte se na navrhování skvělých objektů a třídy považujte především za plány pro objekty - strukturu, ve které definujete proměnné instance a metody instance, které tvoří vaše dobře navržené objekty. Kromě toho si můžete myslet, že třídy poskytují několik speciálních služeb, které objekty nemohou poskytovat, nebo nemohou poskytovat tak elegantně. Představte si třídy jako:

  • správné místo pro definování „obslužných metod“ (metody, které přijímají vstup a poskytují výstup pouze prostřednictvím předaných parametrů a návratové hodnoty)
  • způsob řízení přístupu k objektům a datům

Úžitkové metody

Metody, které nemanipulují ani nepoužívají stav objektu nebo třídy, které nazývám „obslužné metody“. Metody obslužného programu pouze vrátí určitou hodnotu (nebo hodnoty) vypočítanou pouze z dat předaných metodě jako parametry. Měli byste takové metody statické a umístit je do třídy, která nejvíce souvisí se službou, kterou metoda poskytuje.

Příkladem užitné metody je Řetězec copyValueOf (char [] data) metoda třídy Tětiva. Tato metoda produkuje svůj výstup, návratovou hodnotu typu Tětiva, pouze ze svého vstupního parametru, pole chars. Protože copyValueOf () nepoužívá ani neovlivňuje stav žádného objektu nebo třídy, jedná se o metodu obsluhy. A jako by měly být všechny metody obsluhy, copyValueOf () je třídní metoda.

Takže jedním z hlavních způsobů, jak používat metody třídy, jsou metody utility - metody, které vracejí výstup vypočítaný pouze ze vstupních parametrů. Jiná použití metod třídy zahrnují proměnné třídy.

Proměnné třídy pro skrývání dat

Jedním ze základních principů v objektově orientovaném programování je skrývání dat - omezení přístupu k datům, aby se minimalizovaly závislosti mezi částmi programu. Pokud má určitá část dat omezenou přístupnost, mohou se tato data změnit, aniž by došlo k narušení těch částí programu, které k nim nemají přístup.

Pokud je například objekt potřebný pouze instancemi konkrétní třídy, lze odkaz na něj uložit do proměnné soukromé třídy. To dává všem instancím této třídy praktický přístup k tomuto objektu - instance jej pouze používají přímo - ale žádný jiný kód kdekoli jinde v programu se k němu nemůže dostat. Podobným způsobem můžete použít přístup k balíčku a proměnné chráněné třídy ke snížení viditelnosti objektů, které musí sdílet všichni členové balíčku a podtříd.

Proměnné veřejné třídy jsou jiný příběh. Pokud proměnná veřejné třídy není konečná, jedná se o globální proměnnou: ošklivý konstrukt, který je protikladem skrývání dat. Pro proměnnou veřejné třídy nikdy neexistuje žádná omluva, pokud není konečná.

Konečné proměnné veřejné třídy, ať už primitivní typ nebo odkaz na objekt, slouží užitečnému účelu. Proměnné primitivních typů nebo typu Tětiva jsou jednoduše konstanty, které obecně pomáhají zvyšovat flexibilitu programů (snazší jejich změnu). Kód, který používá konstanty, je snadnější změnit, protože můžete změnit konstantní hodnotu na jednom místě. Veřejné proměnné konečné třídy referenčních typů vám umožňují poskytnout globální přístup k objektům, které jsou globálně potřebné. Například, System.in, System.out, a System.err jsou veřejné proměnné konečné třídy, které poskytují globální přístup ke standardním vstupním výstupům a proudům chyb.

Hlavním způsobem, jak zobrazit proměnné třídy, je tedy mechanismus omezující přístupnost (tj. Skrýt) proměnných nebo objektů. Když kombinujete metody třídy s proměnnými třídy, můžete implementovat ještě složitější zásady přístupu.

Používání metod tříd s proměnnými tříd

Kromě toho, že fungují jako obslužné metody, lze metody třídy použít k řízení přístupu k objektům uloženým v proměnných třídy - zejména k řízení toho, jak jsou objekty vytvářeny nebo spravovány. Dva příklady tohoto druhu třídní metody jsou setSecurityManager () a getSecurityManager () metody výuky Systém. Správce zabezpečení aplikace je objekt, který je stejně jako standardní vstupní, výstupní a chybové proudy potřebný na mnoha různých místech. Na rozdíl od standardních objektů proudu I / O však odkaz na správce zabezpečení není uložen ve veřejné proměnné konečné třídy. Objekt správce zabezpečení je uložen v proměnné soukromé třídy a metody set a get implementují pro objekt speciální zásady přístupu.

Bezpečnostní model Java klade na správce zabezpečení zvláštní omezení. Před verzí Java 2 (dříve známou jako JDK 1.2) začala aplikace svůj život bez správce zabezpečení (getSecurityManager () vrátil nula). První volání na setSecurityManager () ustanovil správce bezpečnosti, který se poté nesměl měnit. Jakákoli následná volání na setSecurityManager () by přineslo bezpečnostní výjimku. V prostředí Java 2 začíná aplikace vždy správcem zabezpečení, ale podobně jako v předchozích verzích je setSecurityManager () metoda vám umožní změna maximálně jednou správce zabezpečení.

Správce zabezpečení poskytuje dobrý příklad toho, jak lze metody třídy použít ve spojení s proměnnými soukromé třídy k implementaci speciální zásady přístupu pro objekty odkazované proměnnými třídy. Kromě metod obsluhy považujte metody třídy za prostředek k vytvoření speciálních zásad přístupu pro odkazy na objekty a data uložená v proměnných třídy.

Pokyny

Hlavním bodem rady uvedené v tomto článku je:

Nezacházejte s třídami jako s objekty.

Pokud potřebujete objekt, udělejte si objekt. Omezte použití proměnných a metod tříd na definování metod obslužných programů a implementaci speciálních druhů zásad přístupu pro objekty a primitivní typy uložené v proměnných tříd. I když nejde o čistý objektově orientovaný jazyk, Java je do značné míry objektově orientovaný a vaše návrhy by to měly odrážet. Mysli na předměty.

Příští měsíc

Příští měsíc Techniky návrhu článek bude poslední v tomto sloupci. Brzy začnu psát knihu založenou na materiálu Design Techniques, Flexibilní Java, a umístí tento materiál na mé webové stránky, jak jdu. Sledujte tedy tento projekt a pošlete mi zpětnou vazbu. Po přestávce měsíce nebo dvou se vrátím JavaWorld a SunWorld s novým sloupcem zaměřeným na Jini.

Žádost o účast čtenáře

Doporučuji vaše komentáře, kritiky, návrhy, plameny - všechny druhy zpětné vazby - k materiálu uvedenému v tomto sloupci. Pokud s něčím nesouhlasíte nebo máte co dodat, dejte mi prosím vědět.

Můžete se zúčastnit diskusního fóra věnovaného tomuto materiálu, zadat komentář prostřednictvím formuláře ve spodní části článku nebo mi poslat e-mail přímo pomocí odkazu uvedeného v mém životopisu níže.

Bill Venners píše software profesionálně již 12 let. Se sídlem v Silicon Valley poskytuje softwarové poradenství a školení pod názvem Artima Software Company. V průběhu let vyvinul software pro spotřební elektroniku, vzdělávání, polovodiče a odvětví životního pojištění. Programoval v mnoha jazycích na mnoha platformách: montážní jazyk na různých mikroprocesorech, C na Unixu, C ++ na Windows, Java na webu. Je autorem knihy Inside the Java Virtual Machine, vydané McGraw-Hill.