例子:一個可以給人搭配不同服飾的系統,即可以換各種各樣的衣服褲子的個人形象系統
最先想到的是,先建一個Person類
package deractor;
public class Person {
private String name;
public Person(String name){
this.name=name;
}
public void show(){
System.out.println("裝扮"+name);
}
}
各種服飾的抽象類
package deractor;
abstract class Finery {
public abstract void Show();
}
服飾子類
package deractor;
public class TShirts extends Finery{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("大T恤");
}
}
package deractor;
public class BigTrouser extends Finery{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("垮褲");
}
}
package deractor;
public class WearSneakers extends Finery{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("破球鞋");
}
}
package deractor;
public class WearSuit extends Finery{
@Override
public void Show() {
// TODO Auto-generated method stub
System.out.println("西裝");
}
}
測試代碼
package deractor;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person test=new Person("Autumn");
System.out.println("裝扮如下");
Finery ts=new TShirts();
Finery bt=new BigTrouser();
Finery ws=new WearSneakers();
Finery wsuit=new WearSuit();
ts.Show();
bt.Show();
ws.Show();
wsuit.Show();
}
}
Test中,把“大T恤”、“垮褲”、“破球鞋”、“西裝”一個一個進行顯示,好比:你光着身子,當着大家的面,一件一件穿上衣服,so,應該在內部組裝完畢
即裝飾模式Decorator,動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更爲靈活。
其中,Component定義一個對象接口,可以給這些對象動態地添加職責。ConcreteComponent定義了一個具體的對象,也可以給這個對象添加一些職責。Decorator裝飾抽象類,繼承了Component,從外類來擴展Component類的功能,但對於Component來說,無需知道Decorator的存在,至於ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。基本代碼實現如下:
package deractor;
abstract class Component {
public abstract void Operation();
}
package deractor;
public class ConcreteComponent extends Component{
@Override
public void Operation() {
// TODO Auto-generated method stub
System.out.println("具體的操作對象");
}
}
package deractor;
abstract class Decorator extends Component{
protected Component component;
public void setComponent(Component component){
this.component=component;
}
// 重寫Operation,實際執行的是Component的Operation
public void Operation(){
if(component!=null){
component.Operation();
}
}
}
package deractor;
public class ConcreteDecoratorA extends Decorator{
private String addedState;
public void Operation(){
super.Operation();//首先運行原Operation,再執行本類的功能,如addedState,相當於對原Component進行了裝飾
addedState="new state";
System.out.println("具體裝飾對象A的操作");
}
}
package deractor;
public class ConcreteDecoratorB extends Decorator{
public void Operation(){
super.Operation();
AddedBehavior();
System.out.println("具體裝飾對象B的操作");
}
private void AddedBehavior(){
}
}
裝飾的方法是:先用ConcreteComponent實例化對象c,然後用ConcreteDecoratorA的實例化對象d1來包裝c,再用ConcreteDecoratorB的對象d2包裝d1,最終執行d2的Operation
package deractor;
public class DeTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConcreteComponent c=new ConcreteComponent();
ConcreteDecoratorA d1=new ConcreteDecoratorA();
ConcreteDecoratorB d2=new ConcreteDecoratorB();
d1.setComponent(c);
d2.setComponent(d1);
d2.Operation();
}
}
如果只有一個ConcreteComponent類而沒有抽象的Component類,那麼Decorator類可以是ConcreteComponent的一個子類,如果只有一個ConcreteDecorator類,那麼就沒有必要建立一個單獨的Decorator類,而是可以把Decorator和ConcreteDecorator的責任合併成一個類
將上述衣服搭配稍作修改
package deractor;
public class PersonConcreteComponent {
private String name;
public PersonConcreteComponent(){}
public PersonConcreteComponent(String name){
this.name=name;
}
public void Show(){
System.out.println("裝扮的"+name);
}
}
package deractor;
public class FineryDecorator extends PersonConcreteComponent{
protected PersonConcreteComponent component;
public void Decorate(PersonConcreteComponent component){
this.component=component;
}
public void Show(){
if(component!=null){
component.Show();
}
}
}
package deractor;
public class TShirts2 extends FineryDecorator{
@Override
public void Show() {
// TODO Auto-generated method stub
super.Show();
System.out.println("大T恤");
}
}
package deractor;
public class WearSneakers2 extends FineryDecorator{
@Override
public void Show() {
// TODO Auto-generated method stub
super.Show();
System.out.println("破球鞋");
}
}
package deractor;
public class BigTrouser2 extends FineryDecorator{
@Override
public void Show() {
// TODO Auto-generated method stub
super.Show();
System.out.println("垮褲");
}
}
package deractor;
public class DecorateTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
PersonConcreteComponent person=new PersonConcreteComponent("Autumn");
System.out.println("the following裝扮");
TShirts2 ts=new TShirts2();
BigTrouser2 bt=new BigTrouser2();
WearSneakers2 ws=new WearSneakers2();
ts.Decorate(person);
bt.Decorate(ts);
ws.Decorate(bt);
ws.Show();
}
}
運行結果:
the following裝扮
裝扮的Autumn
大T恤
垮褲
破球鞋
由此可以看出,裝飾模式把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它索要裝飾的對象,因此,當需要執行特殊行爲時,客戶代碼就可以在運行時根據需要有選擇地、按順序地使用裝飾功能包裝對象。