一、服饰搭配系统
现在要求你写一个可以给人搭配不同的服饰的系统,比如类似QQ、网游都有的Avatar系统。你怎么开发呢?
二、小菜扮靓第一版
// Person类
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
// 服装抽象类
public abstract class Finery {
public abstract void show();
}
// 各种服饰子类
public class Tshirt extends Finery {
@Override
public void show() {
System.out.println("T恤");
}
}
public class BigTrouser extends Finery {
@Override
public void show() {
System.out.println("垮裤");
}
}
public class Sneakers extends Finery {
@Override
public void show() {
System.out.println("球鞋");
}
}
// 客户端代码
public class RunMain {
public static void main(String[] args) {
Person xc = new Person("小菜");
// 第一种装扮
Finery t = new Tshirt();
Finery b = new BigTrouser();
Finery s = new Sneakers();
t.show();
b.show();
s.show();
xc.show();
}
}
三、装饰模式
// 定义一个对象接口,可以给对象动态添加职责
public abstract class Component {
public abstract void Operation();
}
// 定义一个具体的对象,可以给对象添加职责
public class ConcreteComponent extends Component {
@Override
public void Operation() {
System.out.println("具体对象的操作");
}
}
// 装饰抽象类,继承Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的
public class Decorator extends Component {
protected Component component;
// 设置Component
public void setComponent(Component component) {
this.component = component;
}
// 重写Operation(),实际执行的是Component的Operation()
@Override
public void Operation() {
if(component!=null){
component.Operation();
}
}
}
// ConcreteDecorator具体的装饰对象,起到给Component添加职责的功能
public class ConcreteDecoratorA extends Decorator {
// 本类独有功能,以区别于ConcreteDecoratorB
private String addedState;
// 首先运行原Component的Operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰
@Override
public void Operation() {
super.Operation();
this.addedState = "New State";
System.out.println("具体装饰对象A的操作");
}
}
public class ConcreteDecoratorB extends Decorator {
@Override
public void Operation() {
super.Operation();
addedBehavior();
System.out.println("具体装饰对象B的操作");
}
//本类独有方法,以区别于ConcreteDecoratorA
private void addedBehavior() {
}
}
public class RunMain {
public static void main(String[] args) {
ConcreteComponent cc = new ConcreteComponent();
ConcreteDecoratorA cda = new ConcreteDecoratorA();
ConcreteDecoratorB cdb = new ConcreteDecoratorB();
// 首先通过ConcreteComponent实例化对象cc,然后通过ConcreteDecoratorA实例化对象cda来包装cc,再通过ConcreteDecoratorB实例化对象cdb来包装cda,最终执行cdb的Operation()
cda.setComponent(cc);
cdb.setComponent(cda);
cdb.Operation();
}
}
四、小菜扮靓第二版
通过装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
// 具体Person类 ConcreteComponent
public class ConcretePerson {
private String name;
public ConcretePerson() {}
public ConcretePerson(String name) {
this.name = name;
}
public void show() {
System.out.println("装扮的" + name);
}
}
// 服饰类 Decorator
public class Finery extends ConcretePerson {
protected ConcretePerson person;
// 设置Component
public void setPerson(ConcretePerson person) {
this.person = person;
}
// 重写Operation(),实际执行的是Component的Operation()
@Override
public void show() {
if(person!=null){
System.out.println("这是具体装饰的操作\n");
person.show();
}
}
}
// 具体服饰类 ConcreteDecorator
public class Tshirt extends Finery {
@Override
public void show() {
System.out.println("T恤");
super.show();
}
}
public class BigTrouser extends Finery {
@Override
public void show() {
System.out.println("垮裤");
super.show();
}
}
public class Sneakers extends Finery {
@Override
public void show() {
System.out.println("球鞋");
super.show();
}
}
// 客户端代码
public class RunMain {
public static void main(String[] args) {
ConcretePerson xc = new ConcretePerson("小菜");
Tshirt t = new Tshirt();
BigTrouser b = new BigTrouser();
Sneakers s = new Sneakers();
t.setPerson(xc);
b.setPerson(t);
s.setPerson(b);
s.show();
}
}
五、总结
装饰模式是为已有功能动态地添加更多功能的一种方式。
当系统需要新功能的时候,向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。
装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
装饰模式有效地把类的核心职责和装饰功能区分开。而且可以去除相关类中重复的装饰逻辑。