zoukankan      html  css  js  c++  java
  • 装饰模式,代理模式,继承

    1:装饰模式举例:

    定义一个接口Food:

    public interface Food {
    
        // 打印出食材
        public void printIngredients();
    }

    简单的炒个米饭:

    public class Rice implements Food{
    
        @Override
        public void printIngredients() {
            System.out.println("Rice");
        }
    }

    Test:

    public static void main(String[] args) {
            Food rice = new Rice();
            rice.printIngredients();
        }

    打印出:

    Rice

    这时候想加个蛋:

    public class RiceFriedWithEgg implements Food{
    
        private Food food;
    
        public RiceFriedWithEgg(Food food) {
            this.food = food;
        }
    
        @Override
        public void printIngredients() {
            System.out.println("Egg");
            food.printIngredients();
        }
    }

    Test:

    public static void main(String[] args) {
            Food rice = new Rice();
            rice = new RiceFriedWithEgg(rice);
            rice.printIngredients();
        }

     打印:

    Egg
    Rice

    (1)RiceFriedWithEgg为装饰对象,Rice为被装饰对象。

    (2)装饰对象RiceFriedWithEgg包含被装饰对象Rice的引用,装饰对象在被装饰对象执行之前或者之后添加附加功能,

    (3)以上例子中,在打印Rice的前面,加上Egg。这样就确保了在炒饭Rice这个类不改变的情况下,加上Egg,生成蛋炒饭,以此达到添加功能的效果。

    2:使用装饰模式相对于继承的好处:

    举个例子,我们先定义一个Animal接口:

    public interface Animal {
    
        public void action();
    }

    然后定义一只Pig实现该接口:

    public class Pig implements Animal {
        @Override
        public void action() {
            System.out.println("pig eat");
        }
    }

    再定义一只Bird:

    public class Bird implements Animal{
    
        @Override
        public void action() {
            System.out.println("bird eat");
        }
    }

    Test:

     public static void main(String[] args) {
            Animal pig = new Pig();
            pig.action();
    
            Animal bird = new Bird();
            bird.action();
        }

    打印出:

    pig eat
    bird eat

    现在有新的需求,要给Pig这个类加一个需求,eat之后run,给Bird这个类加一个需求,吃完之后fly,一般的做法是在Pig和Bird各自添加该功能:

    Pig:

    public class Pig implements Animal{
    
        @Override
        public void action() {
            System.out.println("pig eat");
    run(); } public void run(){ System.out.println("pig run"); } }

    Bird:

    public class Bird implements Animal{
    
        @Override
        public void action() {
            System.out.println("bird eat");
         fly(); } public void fly(){ System.out.println("bird fly"); } }

    打印出:

    pig eat
    pig run
    bird eat
    bird fly

    现在只有两个动物Pig和Bird还好,如果还有Rabbit、Tiger、Fish等等,如果使用继承的话,会有很多组合,会比较麻烦,下面来看看装饰模式的做法:

    Pig还是保持原来的不变:

    public class Pig implements Animal{
    
        @Override
        public void action() {
            System.out.println("pig eat");
        }
    }

    给他添加一个Run的装饰:

    public class Run implements Animal{
        Animal animal = null;
    
        public Run(Animal animal) {
            this.animal = animal;
        }
    
        @Override
        public void action() {
         animal.action(); System.out.println(
    "run"); } }

    Bird还是保持原来的:

    public class Bird implements Animal{
    
        @Override
        public void action() {
            System.out.println("bird eat");
        }
    }

    给他加一个Fly的装饰:

    public class Fly implements Animal{
    
        Animal animal = null;
    
        public Fly(Animal animal) {
            this.animal = animal;
        }
    
        @Override
        public void action() {
            animal.action();
            System.out.println("fly");
        }
    }

    Test:

    public static void main(String[] args) {
            Animal pig = new Pig();
            pig = new Run(pig);
            pig.action();
    
            Animal bird = new Bird();
            bird = new Fly(bird);
            bird.action();
    
        }

    打印出:

    pig eat
    run
    bird eat
    fly

    可以看出,我们想要对Pig和Bird增加新功能,但是并没有直接在这两个类上面修改,而是另外设置一个装饰类,想要哪个功能,客户端就直接调用这个装饰类,并且持有原来类的引用。

    而且装饰可以层层嵌套,比如上面的,目前Pig的action包括eat和run,如果我想让他也有fly的功能,可以这样做:

    public static void main(String[] args) {
            Animal pig = new Pig();
            pig = new Run(pig);
            pig = new Fly(pig);
            pig.action();
        }

    结果:

    pig eat
    run
    fly

    首先是new Pig,是一只pig,想要让他有Run的功能,就new 一个Run的装饰类,并持有pig的引用。再想让他有Fly的功能,就new一个Fly装饰类,并持有pig的引用。

    这个过程充分体现了装饰模式的灵活性,并且我们不需要去改变原来的Pig类就能够达到增加功能的效果。

    这时候如果来的新需求是增加Tiger、Rabbit等,我们就按照Pig和Bird的方式增加新的类,如果是要给各种动物增加新的功能,比如Tiger要加Run和Breath,我们看前面已经有了Run的装饰类,

    就只需要增加一个Breath的装饰类,然后用Run和Breath来装饰Tiger。Rabbit的需求是Run和Eat,那就不需要增加任何装饰类,直接用现成的就行。

    3:装饰模式的缺点:

    每个特点都需要设计成一个装饰类,会有比较多的类产生

    4:和代理模式(静态代理)的区别:

    举个买房子的例子:

    定义一个接口:

    public interface Consumer {
        public void buyHouse();
    }

    一个叫Jack的人要买房子:

    public class Jack implements Consumer{
    
        @Override
        public void buyHouse() {
            System.out.println("buy house");
        }
    }

    但是肯定是要找中介帮忙,中介Agency在帮Jack买房子的时候忙前忙后的做了很多事情:

    public class Agnecy implements Consumer{
    
        private Consumer consumer;
    
        public Agnecy() {
            this.consumer = new Jack();
        }
    
        @Override
        public void buyHouse() {
            System.out.println("do many task....");
            consumer.buyHouse();
            System.out.println("do many task again....");
        }
    }

    Test:

     public static void main(String[] args) {
            Consumer consumer = new Agnecy();
            consumer.buyHouse();
        }

    结果:

    do many task....
    buy house
    do many task again....

    现在来说说代理模式和装饰模式的区别:

    1)先从客户端调用的角度来看看区别:对于客户端来说,他们的真实类分别是Jack和Pig,但是Jack对于客户端是隐藏的,创建该对象的实例是在代理类Agency。

    而对于装饰模式,真实类Pig是客户端定义的,他作为参数传递给装饰类的构造器。

    即代理模式,类的关系客户端不需要去关注,只要使用代理类就可以,而装饰模式,类的各种组合,需要客户端自己去制定。

    代理模式:

    public static void main(String[] args) {
            Consumer consumer = new Agnecy();
            consumer.buyHouse();
        }

    装饰模式:

    public static void main(String[] args) {
            Animal pig = new Pig();
            pig = new Run(pig);
            pig = new Fly(pig);
            pig.action();
        }
  • 相关阅读:
    JavaScript学习之路-语法
    JavaScript学习之路-语法
    JavaScript学习之路-为什么要学习JavaScript语法
    JavaScript学习之路-为什么要学习JavaScript语法
    net4:Panel动态添加控件及隐藏,Table动态创建表格
    net1:DateTime,Application与Session,
    C#精髓第四讲 GridView 72般绝技
    J2ME开发基本语法及小实例专题
    net6:创建Membership对象数据源的代码
    net4:GridView中的重要操作(添加checkbox,以及鼠标动作,行颜色等)
  • 原文地址:https://www.cnblogs.com/wnpp/p/15270648.html
Copyright © 2011-2022 走看看