设计模式(十六)——装饰模式

一、
以人及其属性为例:

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

class highChinese extends Chinese {
	public void desc() {
		super.desc();
		System.out.println("是high人");
	}
}

class richChinese extends Chinese {
	public void desc() {
		super.desc();
		System.out.println("是rich人");
	}
}

class highrichChinese extends Chinese {
	public void desc() {
		super.desc();
		System.out.println("是high&rich人");
	}
}

class HighAmerican extends American {
	public void desc() {
		super.desc();
		System.out.println("是high人");
	}
}

class RichAmerican extends American {
	public void desc() {
		super.desc();
		System.out.println("是rich人");
	}
}

class HighRichAmerican extends American {
	public void desc() {
		super.desc();
		System.out.println("是high&rich人");
	}
}

public class Main {
	public static void main(String[] args) {
		highChinese hc = new highChinese();
		hc.setName("yaoming");
		richChinese rc = new richChinese();
		rc.setName("mayun");
		HighRichAmerican hra = new HighRichAmerican();
		hra.setName("tom");
		hc.desc();
		rc.desc();
		hra.desc();
	}
}

缺点:随着需求的变化,子类会急剧增多,充斥着重复代码,此时的关键是划清责任。

改进版本一(组合代替继承):

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

class highChinese extends Chinese {
	Chinese person;

	public void desc() {
		super.desc();
		System.out.println("是high人");
	}

	public highChinese(Chinese person) {
		this.person = person;
	}
}

class richChinese extends Chinese {
	Chinese person;

	public void desc() {
		super.desc();
		System.out.println("是rich人");
	}

	public richChinese(Chinese person) {
		this.person = person;
	}
}

class highrichChinese extends Chinese {
	Chinese person;

	public void desc() {
		super.desc();
		System.out.println("是high&rich人");
	}

	public highrichChinese(Chinese person) {
		this.person = person;
	}
}

class HighAmerican extends American {
	American person;

	public void desc() {
		super.desc();
		System.out.println("是high人");
	}

	public HighAmerican(American person) {
		this.person = person;
	}
}

class RichAmerican extends American {
	American person;

	public void desc() {
		super.desc();
		System.out.println("是rich人");
	}

	public RichAmerican(American person) {
		this.person = person;
	}
}

class HighRichAmerican extends American {
	American person;

	public void desc() {
		super.desc();
		System.out.println("是high&rich人");
	}

	public HighRichAmerican(American person) {
		this.person = person;
	}
}

public class Main {
	public static void main(String[] args) {
		Chinese p = new Chinese();
		p.setName("yaoming");
		highChinese hc = new highChinese(p);
		hc.desc();
		p.setName("mayun");
		richChinese rc = new richChinese(p);
		rc.desc();
		American q = new American();
		q.setName("rom");
		HighRichAmerican hra = new HighRichAmerican(q);
		hra.desc();
	}
}

继续改进,可以用基类代替子类,消除编译时的依赖;
如:

class highChinese extends Chinese {
	Person person; //基类代替子类,消除编译时的依赖

	public void desc() {
		super.desc();
		System.out.println("是high人");
	}

	public highChinese(Person person) {
		this.person = person;
	}
}
//......其他类似

消除重复,highChinese与highAmerican可以合并为:highPerson等。

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

class highPerson {
	Person person; // 基类代替子类,消除编译时的依赖

	public void desc() {
		person.desc();
		System.out.println("是high人");
	}

	public highPerson(Person person) {
		this.person = person;
	}
}

class richPerson {
	Person person;

	public void desc() {
		person.desc();
		System.out.println("是rich人");
	}

	public richPerson(Person person) {
		this.person = person;
	}
}

class highrichPerson {
	Person person;

	public void desc() {
		person.desc();
		System.out.println("是high&rich人");
	}

	public highrichPerson(Person person) {
		this.person = person;
	}
}

public class Main {
	public static void main(String[] args) {
		Chinese p = new Chinese();
		p.setName("yaoming");
		highPerson hc = new highPerson(p);
		hc.desc();
		p.setName("mayun");
		richPerson rc = new richPerson(p);
		rc.desc();
		American q = new American();
		q.setName("rom");
		highrichPerson hra = new highrichPerson(q);
		hra.desc();
	}
}

发现问题 : 为了保证从继承转组合以后的抽象接口函数public void desc() 遵循接口规范 ,即继承基类设置的抽象接口函数public void desc() 。还是需要通过继承来完善接口规范,不过只需要继承基类Person。

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

class highPerson extends Person {
	Person person; // 基类代替子类,消除编译时的依赖

	public void desc() {
		person.desc();
		System.out.println("是high人");
	}

	public highPerson(Person person) {
		this.person = person;
	}
}

class richPerson extends Person {
	Person person;

	public void desc() {
		person.desc();
		System.out.println("是rich人");
	}

	public richPerson(Person person) {
		this.person = person;
	}
}

class highrichPerson extends Person {
	Person person;

	public void desc() {
		person.desc();
		System.out.println("是high&rich人");
	}

	public highrichPerson(Person person) {
		this.person = person;
	}
}

public class Main {
	public static void main(String[] args) {
		Chinese p = new Chinese();
		p.setName("yaoming");
		highPerson hc = new highPerson(p);
		hc.desc();
		p.setName("mayun");
		richPerson rc = new richPerson(p);
		rc.desc();
		American q = new American();
		q.setName("rom");
		highrichPerson hra = new highrichPerson(q);
		hra.desc();
	}
}

继续发现问题:根据重构,当类中含有重复字段和方法 ,应该将其提到基类中去。
解决:设计一个中间基类 。这样就引出了装饰模式 。
改进版本二(使用装饰模式 改进版本二(使用装饰模式< 中间基类>)

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

abstract class DecoratorPerson extends Person {
	Person person;

	public DecoratorPerson(Person person) {
		this.person = person;
	}
}

class highPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public highPerson(Person person) {
		super(person);
	}

}

class richPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public richPerson(Person person) {
		super(person);
	}

}

class highrichPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public highrichPerson(Person person) {
		super(person);
	}

}

public class Main {
	public static void main(String[] args) {
		Chinese p = new Chinese();
		p.setName("yaoming");
		highPerson hc = new highPerson(p);
		hc.desc();
		p.setName("mayun");
		richPerson rc = new richPerson(p);
		rc.desc();
		American q = new American();
		q.setName("rom");
		highrichPerson hra = new highrichPerson(q);
		hra.desc();
	}
}

此时,无论是增加国家还是增加属性只需增加一个类。
扩展操作,对各国人进行 操作,增加一个属性:

abstract class Person {
	String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public abstract void desc();
}

class Chinese extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println(name + "是中国人");
	}

}

class American extends Person {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		System.out.println("是米国人");
	}

}

abstract class DecoratorPerson extends Person {
	Person person;

	public DecoratorPerson(Person person) {
		this.person = person;
	}
}

class highPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public highPerson(Person person) {
		super(person);
	}

}

class richPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public richPerson(Person person) {
		super(person);
	}

}

class highrichPerson extends DecoratorPerson {

	@Override
	public void desc() {
		// TODO Auto-generated method stub
		person.desc();
		System.out.println("是high人");
	}

	public highrichPerson(Person person) {
		super(person);
	}

}

class handsomePerson extends DecoratorPerson {
	// 为避免重复,实现接口继承DecoratorPerson
	// Person person; // 基类代替子类,消除了编译时依赖
	public void desc() {
		person.desc();
		System.out.println(" 是handsome 人");
	}

	public handsomePerson(Person person) {
		super(person);
	}
};

public class Main {
	public static void main(String[] args) {
		Chinese p = new Chinese();
		p.setName("yaoming");
		highPerson hc = new highPerson(p);
		hc.desc();
		p.setName("mayun");
		richPerson rc = new richPerson(p);
		rc.desc();
		American q = new American();
		q.setName("rom");
		// highrichPerson hra = new highrichPerson(q);
		// hra.desc();
		highPerson hp = new highPerson(p);
		richPerson rp = new richPerson(hp);
		rp.desc();
		handsomePerson hsp = new handsomePerson(rc);
		hsp.desc();
		hc = new highPerson(hsp);
		hc.desc();
	}
}

二、装饰模式(Decorator)
装饰模式是动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加的灵活。

//Component类
abstract class Component{
	public abstract void Operation();
}
//ConcreteComponent类
class ConcreteComponent extends Component{

	@Override
	public void Operation() {
		// TODO Auto-generated method stub
		System.out.println("具体对象的操作");
	}
	
}
//Decorator类
abstract class Decorator extends Component{
	protected Component component;
	public void SetComponent(Component component) {
		this.component=component;
	}
	public void Operation() {
		if(component!=null) {
			component.Operation();
		}
	}
}
//ConcreteDecoratorA类
class ConcreteDecoratorA extends Decorator{
	private String addedState;
	public void Operation() {
		super.Operation();
		addedState="New State";
		System.out.println("具体装饰对象A的操作");
	}
}
class ConcreteDecoratorB extends Decorator{
	public void Operation() {
		super.Operation();
		AddedBehavior();
		System.out.println("具体装饰对象B的操作");
	}

	private void AddedBehavior() {
		// TODO Auto-generated method stub
		
	}
}
public class Main {
	public static void main(String[] args) {
		ConcreteComponent c=new ConcreteComponent();
		ConcreteDecoratorA d1=new ConcreteDecoratorA();
		ConcreteDecoratorB d2=new ConcreteDecoratorB();
		d1.SetComponent(c);
		d2.SetComponent(d1);
		d2.Operation();
	}
}

三、一个可以给人搭配衣服的系统
Person类

class Person {
	private String name;

	public Person(String name) {
		super();
		this.name = name;
	}

	public void WearTShirts() {
		System.out.print("大T恤"+" ");
	}

	public void WearBigTrouser() {
		System.out.print("垮裤"+" ");
	}

	public void WearSneakers() {
		System.out.print("破球鞋"+" ");
	}

	public void WearSuit() {
		System.out.print("西装"+" ");
	}

	public void WearTie() {
		System.out.print("领带"+" ");
	}

	public void WearLeatherShoes() {
		System.out.print("皮鞋"+" ");
	}

	public void Show() {
		System.out.println("装扮的" + name);
	}
}

public class Main {
	public static void main(String[] args) {
		Person xc = new Person("小菜");
		System.out.println("第一种装扮:");
		xc.WearTShirts();
		xc.WearBigTrouser();
		xc.WearSneakers();
		xc.Show();
		System.out.println("第二种装扮:");
		xc.WearSuit();
		xc.WearTie();
		xc.WearLeatherShoes();
		xc.Show();
	}
}

改进:

class Person {
	private String name;

	public Person(String name) {
		super();
		this.name = name;
	}

	public void Show() {
		System.out.println("装扮的" + name);
	}
}

//服饰类
abstract class Finery {
	public abstract void Show();
}

//大T恤
class TShirts extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("大T恤" + " ");
	}

}

class BigTrouser extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("垮裤" + " ");
	}

}

class WearSneakers extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("破球鞋" + " ");
	}

}

class WearSuit extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("西装" + " ");
	}

}

class WearTie extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("领带" + " ");
	}

}

class WearLeatherShoes extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("皮鞋" + " ");
	}

}

public class Main {
	public static void main(String[] args) {
		Person xc = new Person("小菜");
		System.out.println("第一种装扮:");
		Finery dtx = new TShirts();
		Finery kk = new BigTrouser();
		Finery pqx = new WearSneakers();
		dtx.Show();
		kk.Show();
		pqx.Show();
		xc.Show();
		System.out.println("第二种装扮:");
		Finery xz = new WearSuit();
		Finery ld = new WearTie();
		Finery px = new WearLeatherShoes();
		xz.Show();
		ld.Show();
		px.Show();
		xc.Show();
	}
}

用装饰模式改进:

class Person{
	public Person() {
		
	}
	private String name;
	public Person(String name) {
		super();
		this.name = name;
	}
	public void Show() {
		System.out.println("装扮的" + name);
	}
}
class Finery extends Person{
	protected Person component;
	public void Decorate(Person component) {
		this.component=component;
	}
	public void Show() {
		if(component!=null) {
			component.Show();
		}
	}
}
class TShirts extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("大T恤" + " ");
		super.Show();
	}

}

class BigTrouser extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("垮裤" + " ");
		super.Show();
	}

}

class WearSneakers extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("破球鞋" + " ");
		super.Show();
	}

}

class WearSuit extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("西装" + " ");
		super.Show();
	}

}

class WearTie extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("领带" + " ");
		super.Show();
	}

}

class WearLeatherShoes extends Finery {

	@Override
	public void Show() {
		// TODO Auto-generated method stub
		System.out.print("皮鞋" + " ");
		super.Show();
	}

}
public class Main {
	public static void main(String[] args) {
		Person xc=new Person("小菜");
		System.out.println("第一种装扮:");
		WearSneakers pqx=new WearSneakers();
		BigTrouser kk=new BigTrouser();
		TShirts dtx=new TShirts();
		pqx.Decorate(xc);
		kk.Decorate(pqx);
		dtx.Decorate(kk);
		dtx.Show();
		System.out.println("第二种装扮:");
		WearLeatherShoes px=new WearLeatherShoes();
		WearTie ld=new WearTie();
		WearSuit xz=new WearSuit();
		px.Decorate(xc);
		ld.Decorate(px);
		xz.Decorate(ld);
		xz.Show();
	}
}

运行结果:
第一种装扮:
大T恤 垮裤 破球鞋 装扮的小菜
第二种装扮:
西装 领带 皮鞋 装扮的小菜

注:以上部分摘取自朱红梅老师2020年5月的课件。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值