设计模式之结构类模式大PK


结构类模式大PK

装饰模式VS代理模式

  首先要说明的是装饰模式是代理模式的特殊应用,两者的共同点是有相同的接口,不同点事代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,着重类功能的变化。我们看看两者的类图吧!就是一模一样只是代理类和装饰类的名字不一样了而已。我们通过代理类和装饰类看看二者的区别吧。

//代理模式还是侧重于对代理过程的控制,是否允许功能的执行
public class SingerAgent{
       private Singer singer;
       public SingerAgent(Singer singer){
               this.singer = singer;
       }
       public void singing(){
               Random rand = new Random();
               if(rand.nextBoolean()){
                       System.out.println("代理人同意歌手唱歌");
                       singer.sing();
               }else{
                       System.out.println("代理人不同意歌手唱歌");
               }
       }
}
//装饰模式侧重于对装饰对象功能的增强或者减弱
public class SingerWithJet{
        private Singer singer;
        public SingerWithJet(Singer singer){
                this.singer = singer;
        }
        public void singing(){
                System.out.println("歌手的舞蹈优美");
                singer.sing();
        }
}
View Code

  代理模式是把当前行为或功能委托给其它对象执行,代理类负责接口限定:是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,它不对主题角色的功能做任何处理,保证原汁原味的调用。代理模式的极致就是AOP,采用Spring框架必然要使用的技术,它就是使用了代理和反射的技术。

  装饰模式是在要保证接口不变的情况下加强对象的功能,它保证的是被修饰对象功能比原始对象更加丰富,但是不做准入条件和准入参数的判断,是否可以执行类的功能,过滤输入参数是否符合规则等都不是装饰模式关系的内容。

装饰模式VS适配器模式

  装饰模式和适配器模式在类图的设计上差别比较大,但是他们的功能有很多相似的地方,都能够实现包装的作用,通过委托方式实现功能。不同点是:装饰模式包装的是自己的兄弟类,隶属于同一个家族(相同接口或父类),适配器模式则修饰非血缘关系的类,把一个非本家族对象伪装成一个本家族的对象,而对象的本质还是非相同接口的对象。我们还是以丑小鸭的故事来说明这个问题吧。

  首先,我们看看装饰模式实现丑小鸭变白天鹅类图实现。

public interface Swan {
    public void fly();   //飞行能力
    public void cry();   //叫声
    public void desAppearance();   //外表
}

public class UglyDuckling implements Swan{

    @Override
    public void fly() {
        // TODO Auto-generated method stub
        System.out.println("丑小鸭小时候不会飞");
    }

    @Override
    public void cry() {
        // TODO Auto-generated method stub
        System.out.println("咕噜...咕噜");
    }

    @Override
    public void desAppearance() {
        // TODO Auto-generated method stub
        System.out.println("小时候外形是脏兮兮的白色,毛茸茸的大脑袋");
    }

}

public class Decorator implements Swan{
    private Swan swan;
    public Decorator(Swan swan){
        this.swan = swan;
    }
    @Override
    public void fly() {
        // TODO Auto-generated method stub
        swan.fly();
    }

    @Override
    public void cry() {
        // TODO Auto-generated method stub
        swan.cry();
    }

    @Override
    public void desAppearance() {
        // TODO Auto-generated method stub
        swan.desAppearance();
    }
    protected Swan getSwan(){
        return this.swan;
    }

}

public class BeautifulAppearance extends Decorator{

    public BeautifulAppearance(Swan swan) {
        super(swan);
        // TODO Auto-generated constructor stub
    }
    public void desAppearance(){
        super.getSwan().desAppearance();
        System.out.println("纯白色的外表,非常惹人喜爱!");
    }
}

public class StrongBehavior extends Decorator{

    public StrongBehavior(Swan swan) {
        super(swan);
        // TODO Auto-generated constructor stub
    }
    public void fly(){
        super.getSwan().fly();
        System.out.println("长大后的丑小鸭变白天鹅会飞了");
    }
}

public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Swan duck = new UglyDuckling();
        duck.cry();
        duck.fly();
        duck.desAppearance();
        duck = new BeautifulAppearance(duck);
        duck = new StrongBehavior(duck);
        duck.cry();
        duck.fly();
        duck.desAppearance();
    }
}
View Code

   装饰模式实现丑小鸭的蜕变,关注对象功能的强化,是对原始对象的行为和属性的修正和加强,把原本被人视为歧视、冷落的丑小鸭通过两次强化处理最终转变为收人喜爱、羡慕的白天鹅。

  但是通过适配器解决丑小鸭变白天鹅的问题就有点不一样了,我们得把丑小鸭伪装成鸭类,得让她实现鸭类的接口,表现鸭类的行为特征,但是经过时间的推移,丑小鸭终究会变成白天鹅,从而表现出天鹅的特征。为此,需要丑小鸭类继承自天鹅类,从而也实现鸭类的接口。其通用类图如下:鸭类的接口有会叫(void cry())、外观(desAppearance())、其他表现(desBehavior()),天鹅接口有鸣叫、飞翔、以及外观。

public interface IDuck {
    public void cry();   //叫声
    public void desAppearance();    //外观
    public void desBehavior();    //其他表现
}

public interface ISwan {
    public void cry();
    public void desAppearance();
    public void fly();
}

public class WhiteSwan implements ISwan{

    @Override
    public void cry() {
        // TODO Auto-generated method stub
        System.out.println("咕噜...咕噜...");
    }

    @Override
    public void desAppearance() {
        // TODO Auto-generated method stub
        System.out.println("纯白色的羽毛,非常惹人喜爱!");
    }

    @Override
    public void fly() {
        // TODO Auto-generated method stub
        System.out.println("会飞翔");
    }

}

public class UglyDuckling extends WhiteSwan implements IDuck{

    @Override
    public void desBehavior() {
        // TODO Auto-generated method stub
        System.out.println("会游泳");
        super.fly();
    }

    public void cry() {
        super.cry();
    }
    public void desAppearance() {
        super.desAppearance();
    }

}

public class Client {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IDuck uglyDuckling = new UglyDuckling();
        uglyDuckling.cry();
        uglyDuckling.desAppearance();
        uglyDuckling.desBehavior();
    }

}
View Code

  采用适配器模式讲述丑小鸭变天鹅的故事,我们首先观察到的是鸭和天鹅的不同点,建立了不同的接口以实现不同的物种,然后在需要的时候把一个物种伪装成另一个物种,实现不同物种的相同处理过程,这就是适配器模式。

  • 最佳实践
    • 意图不同,装饰模式的意图是加强对象的功能,例子中是把一个自卑的丑小鸭变成一个自信的白天鹅,它不改变类的行为和属性,只是增加功能,而适配器模式则关注的是转化,它的主要意图是两个不同对象之间的转化,它可以把一个天鹅转化为小鸭子看待,也可以把一只小鸭子看成小天鹅,其实就是关注类之间的转化啦。
    • 施与对象不同,装饰对象必须是自己的同宗,也就是相同的接口或父类,只要在具有相同的属性和行为的情况下,才能比较行为是增加还是减弱;适配器模式则必须是不同的两个对象,因为它侧重转化,只有两个不同的对象才有转化的必要。
    • 场景不同,装饰模式在任何时候都可以使用,只要是想增强类的功能,而适配器模式则是一个补救模式,一般出现在系统成熟或已将构建完毕的项目中,作为一个紧急处理手段采用。
    • 扩展性不同,装饰模式很容易扩展,如果不需要装饰,直接去掉装饰类就可以,而且可以继续增加新的装饰类;而适配器模式相当于在两个不同对象之间架起了一座沟通的桥梁,需要从系统整体考虑是否能够撤销。

转载于:https://www.cnblogs.com/zhanglei93/p/6140549.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值