摘要:繼承修改的方法雖然簡單,但是一個已經生成的對象是不能使用繼承來進行這個方法修改的,因為對象已經生成,它的方法就是父類的方法,不能把它轉成子類并進而使用子類方法的。
如何來改變一個對象的中的既有方法呢?
比如如下代碼:
class Dog{ public void bark(){ System.out.println("bark:Wolf-Wolf"); } public void eat(){ System.out.println("eat:BonesBones"); } } public class TestInherit { public static void main(String[] args) { Dog dog = new Dog(); dog.bark(); dog.eat(); } }
我們的目的是將狗叫bark()這個方法改造成另一種實現,這個過程可以有下述的幾種方法來實現:
1.繼承Java繼承是Java作為面向對象的基礎之一,可以用子類方法復寫(override)父類方法
class Dog{ public void bark(){ System.out.println("bark:Wolf-Wolf"); } public void eat(){ System.out.println("eat:BonesBones"); } } class InhDog extends Dog{ public void bark() { System.out.println("bark:WangWangWang"); } } public class TestInherit { public static void main(String[] args) { Dog dog = new InhDog(); dog.bark(); dog.eat(); } }
InhDog繼承Dog后生成的dog對象擁有Dog的類型卻具有InhDog的方法,調用其bark()方法時會調用子類復寫的方法,這個過程也是Java多態性的體現。
Dog dog = new InhDog();
這一句執行使,調用InhDog的構造方法,構造的對象在內存中保存的方法和屬性都是子類具有的,用Dog父類去接使得這個對象變量的類型是父類Dog類型。
繼承修改的方法雖然簡單,但是一個已經生成的對象是不能使用繼承來進行這個方法修改的,因為對象已經生成,它的方法就是父類的方法,不能把它轉成子類并進而使用子類方法的。即如果對象已經生成,那么沒辦法使用繼承的辦法來改變想要改變的方法。
2.裝飾interface Animal{ public void bark(); public void eat(); } class Dog implements Animal{ public void bark(){ System.out.println("bark:Wolf-Wolf"); } public void eat(){ System.out.println("eat:BonesBones"); } } class DecDog implements Animal{ private Animal animal = null; public DecDog(Animal animal){ this.animal = animal; } public void bark() { System.out.println("bark:WangWangWang"); } public void eat() { animal.eat(); } } public class DecTest { public static void main(String[] args) { Dog dog = new Dog(); Animal animal = new DecDog(dog); animal.eat(); animal.bark(); } }
裝飾的實質是將一個類A封裝在另一個類B內部,然后用B類來構造A類,而且A,B都實現同一接口,然后A類控制實現不同的方法,如果要對B類方法進行特殊修飾就重寫該方法,如果不需要就直接使用B的方法。
這個辦法是可以在對象已生成的情況下改變方法的,但是需要對實現的接口進行重新填補抽象方法,抽象方法很多時增加了代碼的冗余。
interface Animal{ public void bark(); public void eat(); } class Dog implements Animal{ public void bark(){ System.out.println("bark:Wolf-Wolf"); } public void eat(){ System.out.println("eat:BonesBones"); } } public class ProxyTest { public static void main(String[] args) { final Dog dog = new Dog(); Animal animal = (Animal) Proxy.newProxyInstance(Dog.class.getClassLoader(), Dog.class.getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("bark".equals(method.getName())){ System.out.println("bark:WangWangWang"); return null; } else{ return method.invoke(dog, args); } } }); animal.bark(); animal.eat(); } }
動態代理的意思是利用代理類來承接原類中的某些方法,本例中使用 Proxy.newProxyInstance方法來創建一個Dog類的代理類實例,代理中定義的invoke方法在每次調用到代理類生成的對象的方法時都會回去訪問該函數,比如利用創建出的animal對象的方法bark()時就會去訪問InvocationHandler()中的invoke方法,并執行invoke方法。在本例中,雖然和裝飾辦法一樣都采用了Animal類型的animal對象,但是不需要復寫其他的抽象方法,只需要把需要復寫的方法多帶帶寫出即可,其他方法只需要用原來的方法就好。可以看出,在創建好對象后,這個辦法是最省力的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64322.html
摘要:簡介代理模式和裝飾者模式是兩種常見的設計模式。這里通過構造函數的參數將被代理對象傳入到代理中,也可以通過其它方式,如提供一個方法。下面是的代碼輸出首先依然是先創建一個需要被代理的對象,然后把它傳入到的構造函數中。 簡介 代理模式和裝飾者模式是兩種常見的設計模式。代理模式是為其它對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以...
摘要:下面總結了它倆的異同相同點都需要實現同一個接口或者繼承同一個抽象類,并且代理角色和裝飾角色都持有被代理角色和構件角色的引用。 寫完上一篇之后有小伙伴問我有沒有寫過代理模式,想看看我的理解。原本我的設計模式系列是按照創建型-行為型-結構型的順序寫下去的,既然小伙伴誠心誠意了,我就大發慈悲的穿插一篇代理模式。開玩笑,題外話。 說起代理模式,就不由得想起經紀人,說起經紀人,就想起了...對,...
摘要:設計模式的分類經典應用框架中常見的設計模式分為三類創建型模式對類的實例化過程的抽象。對象的結構模式是動態的。對象的行為模式則使用對象的聚合來分配行為。設計模式是個好東西,以后肯定還要進一步的學習,并且在項目中多實踐,提升自己的設計能力。 什么是設計模式? Christopher Alexander?說過:每一個模式描述了一個在我們周圍不斷重復發生的問題,以及該問題的解決方案的核心。這樣...
摘要:相關設計模式裝飾者模式和代理模式裝飾者模式關注再一個對象上動態添加方法代理模式關注再對代理對象的控制訪問,可以對客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關于新職責適配器也可以在轉換時增加新的職責,但主要目的不在此。 0x01.定義與類型 定義:裝飾模式指的是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的...
閱讀 1965·2021-09-07 09:59
閱讀 2528·2019-08-29 16:33
閱讀 3702·2019-08-29 16:18
閱讀 2860·2019-08-29 15:30
閱讀 1687·2019-08-29 13:52
閱讀 2050·2019-08-26 18:36
閱讀 545·2019-08-26 12:19
閱讀 708·2019-08-23 15:23