设计模式-装饰器模式
装饰器模式(Decorator Pattern)是一种设计模式,它允许在运行时为对象动态地添加新的行为和责任。这种模式是在不改变现有类结构的情况下,通过创建一个包装对象(即装饰器)来包裹真实对象,并向此装饰器添加额外的功能。
装饰器模式的关键在于能够通过组合而非继承的方式扩展对象的功能,从而提供更大的灵活性。
抽象提取理论:
- 封装变化
- 组合而非继承
- 透明代理
- 开闭原则
代码需求:为游戏角色更换服装,例如第一套服装是大T恤,垮裤,球鞋。第二套服装是西装,领带,皮鞋。你会如何设计呢?
装饰器实现
代码结构图
- 抽象组件:人物形象
- 具体组件:人
- 抽象装饰:服饰
- 具体装饰:大T恤,垮裤,球鞋; 西装,领带,皮鞋
代码实现:
/**
* 人物形象接口
*/
public interface ICharacter {
/**
* 基础方法
*/
void show();
}
/**
* 人
*/
public class Person implements ICharacter{
/** 名称 */
private String name;
/**
* 姓名赋值
*/
public Person(String name){
this.name = name;
}
@Override
public void show() {
System.out.print("我是" + name + "我的服装是: ");
}
}
/**
* 装饰器
*/
public class Finery implements ICharacter{
/** 具体装饰 */
protected ICharacter iCharacter;
/**
* 具体装饰赋值
*/
public void setComponent(ICharacter iCharacter) {
this.iCharacter = iCharacter;
}
@Override
public void show() {
if (iCharacter != null){
// 调用具体装饰方法
this.iCharacter.show();
}
}
}
/**
* 具体服饰-大T恤
*/
public class TShirts extends Finery{
@Override
public void show(){
super.show();
System.out.print(" 大T恤");
}
}
/**
* 具体服饰-垮裤
*/
public class Sneakers extends Finery{
@Override
public void show()
{
super.show();
System.out.print(" 垮裤");
}
}
/**
* 具体服饰-西装
*/
public class Suit extends Finery{
@Override
public void show(){
super.show();
System.out.print(" 西装");
}
}
/**
* 具体服饰-领带
*/
public class Tie extends Finery{
@Override
public void show(){
super.show();
System.out.print(" 领带");
}
}
/**
* 客户端
*/
public class DecoratorDemo {
public static void main(String[] args) {
// 定义人信息
Person person = new Person("小明");
// 第一套服装 先穿衣服,穿裤子
TShirts tShirts = new TShirts();
tShirts.setComponent(person);
Sneakers sneakers = new Sneakers();
sneakers.setComponent(tShirts);
sneakers.show();
System.out.println();
// 第二套服装 先穿西装,再上领带
Suit suit = new Suit();
suit.setComponent(person);
Tie tie = new Tie();
tie.setComponent(suit);
tie.show();
System.out.println();
}
}
输出结果:
Connected to the target VM, address: '127.0.0.1:20955', transport: 'socket'
我是小明我的服装是: 大T恤 垮裤
我是小明我的服装是: 西装 领带
Disconnected from the target VM, address: '127.0.0.1:20955', transport: 'socket'
Process finished with exit code 0