當我們聊裝飾的時候,我們在聊什么?
裝飾模式又稱為包裝模式,如何解釋該模式呢?
從需求出發,我們希望存在這樣一種設計,在不改變原有載體基礎屬性的前提下更換載體的一些外在屬性,從而改變其對外的展示形態,或者動態增加其功能,
開頭為什么要提到 又稱為 ”包裝模式“ 呢?那就是在我們程式的設計上,會突出一個 ”包“ 字,給你原有的物件包一層,賦予新的特性和功能,
形象一點,我們以王者榮耀的皮膚和拖尾為例子來構造一個需求,并嘗試對其進行設計,
需求如下:對于一個英雄,我們希望可以對其功能和特效進行拓展,比如添加皮膚,添加拖尾,添加回城特效等,


需求很簡單,但設計并不容易,我們需要考慮通用性和可拓展性,那么需求存在我們開始設計,
一個設計
ok ,從類設計的角度來看,我們考慮一個最簡單滿足需求的設計,并進行分析改進,首先考慮的就是介面和繼承,基本上玩設計都離不開這兩個東西,尤其是玩通用性,
首先給人物一個統一的父類 GameObject
public abstract class GameObject {
// 展示皮膚
public abstract void showSkin();
}
創建一個悟空類繼承 GameObject
public class WuKong extends GameObject{
@Override
public void showSkin() {
System.out.println("原皮膚的悟空");
}
}
那換膚和拖尾呢,我多實作幾個不同的悟空類不就行了?
public class WuKong86AndTrailing extends GameObject{
@Override
public void showSkin() {
System.out.println("86版皮膚的悟空和原始拖尾");
}
}
public class WuKongHellfireAndAdventureTrailing extends GameObject{
@Override
public void showSkin() {
System.out.println("地獄火皮膚的悟空和冒險拖尾");
}
}
使用:
public class Main {
public static void main(String[] args) {
GameObject wk=new WuKong();
wk.showSkin();
GameObject wk2=new WuKong86AndTrailing();
wk2.showSkin();
GameObject wk3=new WuKongHellfireAndAdventureTrailing();
wk3.showSkin();
}
}
輸出:
原皮膚的悟空
86版皮膚的悟空和原始拖尾
地獄火皮膚的悟空和冒險拖尾
到這里,完工!這樣設計有問題嗎?有問題!問題大了,
首先這個設計根本沒有完成我們的需求,雖然說玩了下繼承,但跟沒玩一樣,一個皮膚一個建立一個新的英雄物件,那如果換個英雄呢?完全沒法復用了,子類物件爆炸,
我們在聊什么?
上個設計有問題,好!改!首先我們先分析一下如何改,
- 我們要復用物件,在原始物件的基礎下進行附加,
- 游戲物件和裝飾物件需要抽離
首先我們把介面抽象出來,展示皮膚提到介面里
public interface Component {
void show();
}
統一的游戲基類,給個名字
public abstract class GameObject implements Component{
String name;
public GameObject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println("英雄登場:"+this.name);
}
}
抽象的裝飾器類,我們所有的附加裝飾都要實作該類,該類實作 Component 介面
public abstract class GameObjectDecorator implements Component {
private Component component;
public GameObjectDecorator(Component component) {
this.component = component;
}
@Override
public void show() {
component.show();
addDecorator();
}
public abstract void addDecorator();
}
創建角色,這里創建兩個,來展示其可復用性
public class WuKong extends GameObject {
public WuKong() {
super("悟空");
}
}
public class Human extends GameObject {
public Human() {
super("普通人類");
}
}
皮膚裝飾類:
public class Clothes86Decorator extends GameObjectDecorator {
public Clothes86Decorator(Component component) {
super(component);
}
@Override
public void addDecorator() {
System.out.println("裝備 86 皮膚");
}
}
public class ClothesHellfireDecorator extends GameObjectDecorator {
public ClothesHellfireDecorator(Component component) {
super(component);
}
@Override
public void addDecorator() {
System.out.println("裝備地獄火皮膚");
}
}
拖尾裝飾類:
public class AdventureTrailDecorator extends GameObjectDecorator {
public AdventureTrailDecorator(Component component) {
super(component);
}
@Override
public void addDecorator() {
System.out.println("裝備 冒險拖尾");
}
}
public class TrailDecorator extends GameObjectDecorator {
public TrailDecorator(Component component) {
super(component);
}
@Override
public void addDecorator() {
System.out.println("裝備 原始拖尾");
}
}
使用:
public class Main {
public static void main(String[] args) {
GameObject wuKong=new WuKong();
wuKong.show();
System.out.println();
Clothes86Decorator clothes86Decorator=new Clothes86Decorator(wuKong);
TrailDecorator trailDecorator=new TrailDecorator(clothes86Decorator);
trailDecorator.show();
System.out.println();
ClothesHellfireDecorator clothesHellfireDecorator=new ClothesHellfireDecorator(wuKong);
AdventureTrailDecorator adventureTrailDecorator=new AdventureTrailDecorator(clothesHellfireDecorator);
adventureTrailDecorator.show();
System.out.println();
Human human=new Human();
ClothesHellfireDecorator clothesHellfireDecorator2=new ClothesHellfireDecorator(human);
AdventureTrailDecorator adventureTrailDecorator2=new AdventureTrailDecorator(clothesHellfireDecorator2);
adventureTrailDecorator2.show();
System.out.println();
wuKong.show();
}
}
輸出:
英雄登場:悟空
英雄登場:悟空
裝備 86 皮膚
裝備 原始拖尾
英雄登場:悟空
裝備地獄火皮膚
裝備 冒險拖尾
英雄登場:普通人類
裝備地獄火皮膚
裝備 冒險拖尾
英雄登場:悟空
你會發現我們所有的裝飾類都可以一個套一個,進行無限的附加,這歸功于我們在抽象裝飾器類中,組合了原始的 Component 介面,而我們所有的類都實作的該介面,使得我們在使用時可以進行任意的添加,并形成了這種 “包裝的感覺”,
使用場景
當需要通過對現有的一組基本功能進行排列組合而產生非常多的功能時,或者物件的功能要求可以動態地添加,也可以再動態地撤銷時,考慮使用裝飾模式或許是一個不錯的選擇
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/321462.html
標籤:其他
下一篇:數學知識(習題課)
