0.《设计模式》摘录
-
问题:
动态地给一个对象(不是类)添加一些额外的职责。
从增加功能的角度, Decorate模式比用子类更为灵活。
Decorator和所装饰的对象具有相同的接口,使用它们的程序不必区别它们。 -
对比组合模式:
都是声明一个公共的接口,且有包含关系
但是组合模式是类之间包含,而装饰模式是包含对象
合成模式是为了对组合对象和原始对象有一样的操作,而装饰模式是为了类的功能 -
适用性:
在不影响被装饰对象的情况下,以动态、透明的方式给这个对象增加功能,这些功能可以动态撤销
尤其可以用在以下情况
不能通过继承扩充当前类
或者需要建立大量孤立扩展子类:带边框子类、带横向滚动条子类、带纵向滚动条子类、带边框并且带横向滚动条子类、带边框并且带纵向滚动条子类、 … -
优点
比继承方式灵活:可以动态增减和组合附加的功能
可以避免在设计初期把太多的功能加入高层的类中
高层类可以设计得较为简洁,在具体应用中需要时通过装饰模式增加功能
可能会产生很多小对象,这是对象组合的特点。
在经过初期的实验后,再决定哪些功能通过子类继承加入,哪些通过对象组合加入。
问题
现在需要穿衣服,而有多种多样的衣服。
第一种方案是把人和衣服分开,一个Person类,一个Finery服饰抽象类。Finery有许多继承它的子类,构成不同的服饰,每种服饰都有方法show,选择穿什么衣服就调用什么服饰的show方法。
但这种就好比光着身子,当着大家的面,先穿T恤,再穿裤子,再穿鞋。服饰应该在内部组装完闭,然后再显示出来。问题在于服饰的穿戴顺序不固定,不能使用建造者模式
装饰模式
1.定义
装饰模式(Decorator):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
2.结构和代码
- 结构图:
- Component:抽象的,是我们要装饰的对象,比如上例中就是Peroson
abstract class Component
{
public abstract void Operation();
}
- ConcreteComponent:继承Component,具体实现方法,比如Man,可以继承Person
class ConcreteComponent extends Component
{
public override void Operation()
{
Console. WriteLine ("具体对象的操作");
}
}
-
Decorator:包含一个ConcreteComponent,以便其子类对ConcreteComponent进行装饰,这里是抽象的。
abstract class Decorator extends Component { protected Component component; public void SetComponent(Component) { this.component=component;//包含了一个具体的Componet } public override void Operation()//重写父类的方法 { component.Operation();//实际执行的是 Component 的 Operation } }
-
ConcreteDecoratorA :继承Decrator,还可以加上自己的方法来装饰。
-
那么所谓装饰怎么实现的呢?
先调用父类,并且加上自己的方法,这样就是增加一种装饰。
-
那怎么形成装饰链呢?
装饰类A通过SetComponent传入一个装饰类B,就能让A先调用父类方法(A父类又是调用B的方法),然后再加上A自己的方法,就叠加了装饰。
加入一个装饰类C通过构造器传入了A,C先调用A方法,而A又是先调用其父类方法(A父类又是调用B的方法),然后再调用C。就实现了:
ConcreteComponent.Operation()->B新增装饰->A新增装饰->C新增装饰
class ConcreteDecoratorA extends Decorator { //包含父类的方法SetComponent(),属性component public override void Operation() { super.Operation();//先运行原 Component 的 Operation System.out.print("具体装饰对象A的操作");//再执行本类的功能,相当于对原Component进行了装饰 } } class ConcreteDecoratorB extends Decorator { //包含父类的方法SetComponent(),属性component,方法Operation() public override void Operation() { super.Operation(); System.out.print("具体装饰对象B的操作");//执行本类的功能,相当于对原Component进行了装饰 } }
-
-
客户端:
1.先得到一个ConcreteComponent c
2.然后用ConcreteDecoratorA来包装c,得到d1
3.然后用ConcreteDecoratorB来包装d1,得到d2
4.最后调用d2的方法,d2先调用c的方法,再是A的,再是B的
static void Main (string[] args): { ConcreteComponent c = new ConcreteComponent();//1 ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB (); d1.SetComponent (c);//2 d2.SetComponent (d1);//3 d2.Operation();//4 }
-
注意:抽象类Person和Decorator不是必须的,比如就只有一类人,那可以直接用一个ConcreteComponent。在上例中,就直接用一个具体的Person。
3.解决上述问题的java代码
下面写两种方法,一个是服饰类和他的子类利用构造器来设置属性component
,注意这样的话子类需要复写父类的构造器
一个是通过方法**setComponent(Person p)**来设置属性component
-
Person
class Person { protected String name; Person(String name){ this.name=name; } Person(){} void show() { System.out.println("被修饰的是:"+name); } }
-
Decrator
-
方法一:构造器
abstract class Decrator extends Person { private Person component; Decrator(Person component)//构造器来设置component { this.component=component; } void show() { if(component!=null) { component.show(); } } }
-
方法二:setComponent()
abstract class Decrator extends Person { private Person component; void setComponent(Person component)//设置属性component { this.component=component; } void show() { if(component!=null) { component.show();//调用Person的方法 } } }
-
-
Decrator的子类:Shoes Clothes Pants
-
方法一:要复写父类构造器
class Shoes extends Decrator { Shoes(Person component) { super(component); } void show()//先调用自己新增的装饰,再调用父类的方法 { System.out.println("穿上鞋子的 "); super.show(); } } class Clothes extends Decrator { Clothes(Person component) { super(component); } void show() { System.out.println("穿上衣服的 "); super.show(); } } class Pants extends Decrator { Pants(Person component) { super(component); } void show() { System.out.println("穿上裤子的 "); super.show(); } }
-
方法二:直接继承父类的setComponent()
class Shoes extends Decrator { void show() { System.out.println("穿上鞋子的 "); super.show(); } } class Clothes extends Decrator { void show() { System.out.println("穿上衣服的 "); super.show(); } } class Pants extends Decrator { void show() { System.out.println("穿上裤子的 "); super.show(); } }
-
-
客户端
-
方法一:构造器版本
public class homeWorkTest //客户端代码 { public static void main(String[] args) { Person p=new Person("lxh"); Shoes s=new Shoes(p);//通过构造器包含Person p Pants pants=new Pants(s);//通过构造器包含Person s pants.show(); } }
-
方法二:setComponent版本
public static void main(String[] args) { Person p=new Person("lxh"); Shoes s=new Shoes(); Pants pants=new Pants(); pants.setComponent(p);//通过setComponent包含Person p s.setComponent(pants); s.show(); }
-
-
总的
方法一:public class homeWorkTest { public static void main(String[] args) { Person p=new Person("lxh"); Shoes s=new Shoes(p); Pants pants=new Pants(s); pants.show(); } } class Person { protected String name; Person(String name){ this.name=name; } Person(){} void show() { System.out.println("被修饰的是:"+name); } } abstract class Decrator extends Person { private Person component; Decrator(Person component) { this.component=component; } } void show() { if(component!=null) { component.show(); } } class Shoes extends Decrator { Shoes(Person component) { super(component); } void show() { System.out.println("穿上鞋子的 "); super.show(); } } class Clothes extends Decrator { Clothes(Person component) { super(component); } void show() { System.out.println("穿上衣服的 "); super.show(); } } class Pants extends Decrator { Pants(Person component) { super(component); } void show() { System.out.println("穿上裤子的 "); super.show(); } }
方法二
import java.awt.*; public class homeWorkTest { public static void main(String[] args) { Person p=new Person("lxh"); Shoes s=new Shoes(); Pants pants=new Pants(); pants.setComponent(p); s.setComponent(pants); s.show(); } } class Person { protected String name; Person(String name){ this.name=name; } Person(){} void show() { System.out.println("被修饰的是:"+name); } } abstract class Decrator extends Person { private Person component; void setComponent(Person component) { this.component=component; } void show() { if(component!=null) { component.show(); } } } class Shoes extends Decrator { void show() { System.out.println("穿上鞋子的 "); super.show(); } } class Clothes extends Decrator { void show() { System.out.println("穿上衣服的 "); super.show(); } } class Pants extends Decrator { void show() { System.out.println("穿上裤子的 "); super.show(); } }