喂! 裝飾模式(Decoraor) 說你呢! 禁止套娃!!!

瞭解裝飾模式:

我們來看一下“裝飾”是什麼意思:

(截圖來自百度漢語)

就這個詞,已經快解釋清楚“裝飾模式”是什麼東西了。

 

裝飾模式:動態的將新功能附加到對象上。

怎麼去動態添加?

其實是通過套娃實現的。

而且,沒有什麼附加功能是套娃解決不了的,如果不行,那就套兩層。

我就,模擬養成養魔法魚,做例子來講一下。

 

裝飾模式小案例:

首先咱們建個魚的父類。

這是類的作用相當於管道,把主體類和各個裝飾類鏈接起來。


package 裝飾者模式;

public abstract class AboutFish {
	public AboutFish obj;
	public String des;
	private float price = 0.0f;
	public String getDes() {
		return des;
	}
	public void setDes(String des) {
		this.des = des;
	}
	public float getPrice() {
		return price;
	}
	public void setPrice(float price) {
		this.price = price;
	}
	
	/**
	 * 計算費用的抽象方法,子類實現
	 * @return
	 */
	public abstract float cost();
}

然後寫魔法魚類

這個類是主體類,所有的裝飾都是給他用的。

package 裝飾者模式;

public class Fish extends AboutFish {

	public Fish() {
		setDes("魔法魚魚卵");
		setPrice(10.0f);
	}
	@Override
	public float cost() {
		return super.getPrice();
	}
}

到現在,還沒有用到裝飾。

我們直接開始模擬養成魔法魚。在過程中使用、講述裝飾模式

package 裝飾者模式;

public class Me {

	public static void main(String[] args) {
		// 購買魚卵
		AboutFish fish = new Fish();
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!");
		System.out.println("-----");
	}
}

運行結果:

已經花了:10.0
魔法魚魚卵
已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!
-----

我們開始找水吧!(準備好,開始套娃了

 

首先寫個裝飾抽象類(所有抽象類的父類),接上管道(繼承魚的父類

package 裝飾者模式;

public class Decorator extends AboutFish{

	public Decorator(AboutFish obj) {
		this.obj=obj;
	}
	@Override
	public float cost() {
		return super.getPrice()+obj.cost();
	}
	@Override
	public String getDes() {
		return obj.getDes();
	}
}

然後寫水類(裝飾類

package 裝飾者模式;

public class Water extends Decorator{

	public Water(AboutFish obj) {
		super(obj);
		setDes("水");
		setPrice(0.0f);
	}

}

開始孵化吧!

package 裝飾者模式;

public class Me {

	public static void main(String[] args) {
		// 購買魚卵
		AboutFish fish = new Fish();
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!");
		System.out.println("-----");
		// 獲得水
		fish = new Water(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“水”,請儘快孵化吧");
		System.out.println("-----");
		System.out.println("開始孵化...");
		fish.obj.des="小魚苗";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
        System.out.println("孵化成功,趕快給小魚苗找點喫的吧!");
	}
}

運行結果:

已經花了:10.0
魔法魚魚卵
已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!
-----
已經花了:10.0
魔法魚魚卵
已獲得“水”,請儘快孵化吧
-----
開始孵化...
已經花了:10.0
小魚苗
孵化成功,趕快給小魚苗找點喫的吧!

到此我們已經裝飾了一次了。

繼續給小魚苗尋找食物吧(裝飾類、又套一層娃)。

package 裝飾者模式;

public class 脫殼豐年蝦卵__小魚苗食物 extends Decorator{

	public 脫殼豐年蝦卵__小魚苗食物(AboutFish obj) {
		super(obj);
		setDes("脫殼豐年蝦卵");
		setPrice(5.0f);
	}

}

開始餵食吧。

package 裝飾者模式;

public class Me {

	public static void main(String[] args) {
		// 購買魚卵
		AboutFish fish = new Fish();
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!");
		System.out.println("-----");
		// 獲得水
		fish = new Water(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“水”,請儘快孵化吧");
		System.out.println("-----");
		System.out.println("開始孵化...");
		fish.obj.des="小魚苗";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("孵化成功,趕快給小魚苗找點喫的吧!");
		// 獲得脫殼豐年蝦卵
		fish = new 脫殼豐年蝦卵__小魚苗食物(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“脫殼豐年蝦卵”,請餵食小魚苗,讓它快快長大吧");
		System.out.println("-----");
		System.out.println("開始餵食..");
		fish.obj.obj.des="幼魚";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println(".脫離幼苗期,成爲幼魚,幼魚得喫水蚤!");
	}
}

運行結果:

已經花了:10.0
魔法魚魚卵
已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!
-----
已經花了:10.0
魔法魚魚卵
已獲得“水”,請儘快孵化吧
-----
開始孵化...
已經花了:10.0
小魚苗
孵化成功,趕快給小魚苗找點喫的吧!
已經花了:15.0
小魚苗
已獲得“脫殼豐年蝦卵”,請餵食小魚苗,讓它快快長大吧
-----
開始餵食..
已經花了:15.0
幼魚
.脫離幼苗期,成爲幼魚,幼魚得喫水蚤!

裝飾兩次了。

找水蚤吧(裝飾類、雙套一層娃)。

package 裝飾者模式;

public class 水蚤__幼魚食物 extends Decorator{

	public 水蚤__幼魚食物(AboutFish obj) {
		super(obj);
		setDes("水蚤");
		setPrice(10.0f);
	}

}

開始餵魚:

package 裝飾者模式;

public class Me {

	public static void main(String[] args) {
		// 購買魚卵
		AboutFish fish = new Fish();
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!");
		System.out.println("-----");
		// 獲得水
		fish = new Water(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“水”,請儘快孵化吧");
		System.out.println("-----");
		System.out.println("開始孵化...");
		fish.obj.des="小魚苗";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("孵化成功,趕快給小魚苗找點喫的吧!");
		// 獲得脫殼豐年蝦卵
		fish = new 脫殼豐年蝦卵__小魚苗食物(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“脫殼豐年蝦卵”,請餵食小魚苗,讓它快快長大吧");
		System.out.println("-----");
		System.out.println("開始餵食..");
		fish.obj.obj.des="幼魚";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println(".脫離幼苗期,成爲幼魚,幼魚得喫水蚤!");
		// 獲得水蚤
		fish = new 水蚤__幼魚食物(fish);
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
		System.out.println("已獲得“水蚤”,請餵食幼魚,讓它快快長大吧");
		System.out.println("-----");
		System.out.println("開始餵食...脫離幼魚期,成爲成魚");
		fish.obj.obj.obj.des="成魚";
		System.out.println("已經花了:"+fish.cost());
		System.out.println(fish.getDes());
	}
}

運行結果:

已經花了:10.0
魔法魚魚卵
已獲得“魔法魚魚卵 X1”,有“水”就可以孵化魚卵了,快去尋找“水”吧!
-----
已經花了:10.0
魔法魚魚卵
已獲得“水”,請儘快孵化吧
-----
開始孵化...
已經花了:10.0
小魚苗
孵化成功,趕快給小魚苗找點喫的吧!
已經花了:15.0
小魚苗
已獲得“脫殼豐年蝦卵”,請餵食小魚苗,讓它快快長大吧
-----
開始餵食..
已經花了:15.0
幼魚
.脫離幼苗期,成爲幼魚,幼魚得喫水蚤!
已經花了:25.0
幼魚
已獲得“水蚤”,請餵食幼魚,讓它快快長大吧
-----
開始餵食...脫離幼魚期,成爲成魚
已經花了:25.0
成魚

接下來還有性成熟、交尾、產卵、衰老、死亡,等等。

你可以接着又、雙繼續叒、叕的套下去

今天咱們的娃,就先套到這裏,啊不對,咱們的魚,就先養到這裏吧。

 

畢竟它是一條工具魚。養到這裏,就夠我們理解裝飾模式了。

原理解析:

這是原理圖:

(關於向上轉型,不瞭解的可以看我的另一篇博客學習:Java知識掃盲——向上轉型(類向上轉型、接口向上轉型)以及向上轉型的優勢、靈活運用

這是串起來以後的效果圖:

 

通過這種無限套娃,讓本來的Fish可以經過多次修飾,動態的添加功能。

 

到現在,我想大家已經理解什麼是裝飾模式了。

 

 

裝飾模式的優點:

如大家所見,擴展性非常好,只要套下去就可以了。。。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章