1、装饰(Decorator)模式,循序渐进,从穿衣谈起:写一个可以给人搭配不同服饰的程序,循序渐进,class Personprivate string name;public Person(string name)this.name = name;public void WearTShirts()Console.Write(“大T恤 “);,public void WearBigTrouser()Console.Write(“垮裤 “);public void WearSneakers()Console.Write(“破球鞋 “);,public void WearSuit()Console.
2、Write(“西装 “);public void WearTie()Console.Write(“领带 “);,public void WearLeatherShoes()Console.Write(“皮鞋 “);public void Show()Console.WriteLine(“装扮的0“, name);,客户端,static void Main(string args)Person xc = new Person(“小菜“);Console.WriteLine(“n第一种装扮:“);xc.WearTShirts();xc.WearBigTrouser();xc.WearSneaker
3、s();xc.Show();,Console.WriteLine(“n第二种装扮:“);xc.WearSuit();xc.WearTie();xc.WearLeatherShoes();xc.Show();Console.Read();,缺点,若要增加其它装扮,需要修改Person类,违背了开放封闭原则 试着将这些服饰写成子类,Person类,class Personprivate string name;public Person(string name)this.name = name;public void Show()Console.WriteLine(“装扮的0“, name);,抽
4、象类Finery,abstract class Finerypublic abstract void Show();,class TShirts : Finerypublic override void Show()Console.Write(“大T恤 “);,class BigTrouser : Finerypublic override void Show()Console.Write(“垮裤 “);,。,客户端,static void Main(string args)Person xc = new Person(“小菜“);Console.WriteLine(“n第一种装扮:“);Fi
5、nery dtx = new TShirts();Finery kk = new BigTrouser();Finery pqx = new Sneakers();dtx.Show();kk.Show();pqx.Show();xc.Show();,Console.WriteLine(“n第二种装扮:“);Finery xz = new Suit();Finery ld = new Tie();Finery px = new LeatherShoes();xz.Show();ld.Show();px.Show();xc.Show();Console.Read();,试着将装饰在内部组装完毕,D
6、ecorator,装饰(Decorator)模式又名包装(Wrapper)模式GOF95。 装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。,abstract class Componentpublic abstract void Show(); ,class Person: Componentpublic Person() private string name;public Person(string name)this.name = name;public override void Show()Console.WriteLine(“装扮的0“, name);,cl
7、ass Finery : Componentprotected Component component;public void Decorate(Component component)ponent = component;public override void Show()if (component != null)component.Show();,class TShirts : Finerypublic override void Show()Console.Write(“大T恤 “);base.Show();class BigTrouser : Finerypublic overri
8、de void Show()Console.Write(“垮裤 “);base.Show();,class Sneakers : Finerypublic override void Show()Console.Write(“破球鞋 “);base.Show();class Suit : Finerypublic override void Show()Console.Write(“西装 “);base.Show();,class Tie : Finerypublic override void Show()Console.Write(“领带 “);base.Show(); class Lea
9、therShoes : Finerypublic override void Show()Console.Write(“皮鞋 “);base.Show();,static void main(string args)Person xc = new Person(“小菜“);Console.WriteLine(“n第一种装扮:“);Sneakers pqx = new Sneakers();BigTrouser kk = new BigTrouser();TShirts dtx = new TShirts();pqx.Decorate(xc);kk.Decorate(pqx);dtx.Decor
10、ate(kk);dtx.Show();,Console.WriteLine(“n第二种装扮:“);LeatherShoes px = new LeatherShoes();Tie ld = new Tie();Suit xz = new Suit();px.Decorate(xc);ld.Decorate(px);xz.Decorate(ld);xz.Show();,Console.WriteLine(“n第三种装扮:“);Sneakers pqx2 = new Sneakers();LeatherShoes px2 = new LeatherShoes();BigTrouser kk2 =
11、new BigTrouser();Tie ld2 = new Tie();pqx2.Decorate(xc);px2.Decorate(pqx2);kk2.Decorate(px2);ld2.Decorate(kk2);ld2.Show();Console.Read();,另一种写法,abstract class Componentpublic abstract void Show(); ,class Person: Componentpublic Person() private string name;public Person(string name)this.name = name;p
12、ublic override void Show()Console.WriteLine(“装扮的0“, name);,class Finery : Componentprotected Component component;public void Finery(Component component)ponent = component;public override void Show()if (component != null)component.Show();,class TShirts : Finerypublic TShirts(Component component):base
13、(component) public override void Show()Console.Write(“大T恤 “);base.Show();,static void main(string args)Component xc = new Person(“小菜“);Console.WriteLine(“n第一种装扮:“);Finery pqx = new Sneakers(xc);Finery kk = new BigTrouser(pqx);Finery dtx = new TShirts(kk);dtx.Show(); ,上面的代码在执行装饰时是通过Decorate方法实现的 装饰模式
14、常常被称为包裹模式,就是因为每一个具体装饰类都将下一个具体装饰类或者具体构件类包裹起来。,抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。 具体构件(Concrete Component)角色:实现组件对象接口,通常就是被装饰器装饰的对象。 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。 具体装饰(Concrete Decorator)角色:负责给构件对象“贴上“附加的责任。,装饰模式为对象添加额外责任的方式就像做蛋糕一样,一圈一圈的加上去,中间的面包是核心,是被装饰的对象(Person),
15、是核心任务,外围的都是装饰对象。 这就是说装饰模式包含两部分内容,即装饰对象和被装饰对象。,按照GOF的说法,Decorator模式的意图是:动态的给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。 这个被装饰的对象不一定是最原始的那个对象,也可能是被其他装饰器装饰过的对象,反正都是实现的同一接口,也就是同一类型。 Decorator模式的效果是:让我们可以创建以decorator对象-负责新的功能的对象-开始的一条对象“链”,并结束于最初的对象。,Decorator 链,继承和多态,装饰模式耍了这么绕,其实就用了两招,继承和多态。 所有组件都是Comp
16、onent 的子类,由Component 规划对象的行为(如,public void show();),装饰类Decorator 与 被装饰类Person 都是Component 的子类,那么他们具有相同的行为; 装饰类Decorator 也以Component 为成员变量,那他就有机会操作Component 的所有子类,而Decorator 的子类都override了Decorator 定义的接口,确切的说是Component 定义的接口,这样,各装饰类有了机会重写自己关心的装饰工作。,典型案例(JAVA中的I/O流),public class iotEST public static vo
17、id main(String args) throws Exception DataInputStream din=null;trydin=new DataInputStream(new BufferedInputStream(new FileInputStream(“IOTest.txt“);byte bs=new bytedin.available();din.read(bs);String content=new String(bs);System.out.println(“文件内容=“+content);finallydin.close(); ,同样的,输出流部分也类似,既然I/O流部
18、分是采用装饰模式实现的,如果我们想要添加新的功能,只需要实现新的装饰器,然后再使用时,组合进去就可以。 自己实现的I/O流的装饰器 实现把英文加密存放。,public class EncryptOutputStream extends OutputStreamprivate OutputStream os=null;public EncryptOutputStream(OutputStream os)this.os=os;public void write(int a) throws IOExceptiona=a+2;if(a=(97+26)a=a-26;this.os.write(a); ,
19、public class iotEST public static void main(String args) throws Exception DataOutputStream dout=new DataOutputStream(new BufferedOutputStream(new EncryptOutputStream(new FileOutputStream(“IOTest.txt“);dout.write(“abcdxyz“.getBytes();dout.close(); ,模式讲解,装饰模式的功能 能够实现动态地为对象添加功能,是从一个对象外部来给对象增加功能,相当于是改变了
20、对象的外观。 对象组合 Favor Composition Over Inheritance。装饰模式的思考起点就是这个规则 装饰器和组件类的关系 装饰器是用来装饰组建的,装饰器一定要实现和组件类一致的接口,保证他们是同一个类型,并具有同一个外观,这样组合完成的装饰才能够递归调用下去,本质,动态组合 动态是手段,组合是目的,使用装饰模式主要有以下的优点:,装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。,装饰模式缺点:,会产生很多细粒度对象,装饰模式与策略模式,策略模式
21、改变的是对象的内核 装饰模式改变的是对象的外壳 策略模式是一层调用 装饰模式是递归调用 可以有机结合,装饰模式与AOP,AOP是OOP的延续,是(Aspect Oriented Programming)的缩写,意思是面向方面编程。 面向对象开发中,考虑系统的角度通常是纵向的。,AOP主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。 主要的意图是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。,另一场景,复杂的奖金计算 奖金分类,对于个人有当月奖金、个人累计奖金、个人业务增长奖金、及时回款奖金、限时成交加码奖金等;对于业务主管或者是业务经理,除了个人奖金外,还有团队累积奖金、团队业务增长奖金、团队盈利奖金等。 计算公式也有不同 计算奖金金额的基数也有不同 奖金的计算方式会经常变化。要适于调整和修改,