• 装饰模式,代理模式,继承


    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();
        }
  • 相关阅读:
    leetcode Convert Sorted List to Binary Search Tree
    leetcode Convert Sorted Array to Binary Search Tree
    leetcode Binary Tree Level Order Traversal II
    leetcode Construct Binary Tree from Preorder and Inorder Traversal
    leetcode[105] Construct Binary Tree from Inorder and Postorder Traversal
    证明中序遍历O(n)
    leetcode Maximum Depth of Binary Tree
    限制 button 在 3 秒内不可重复点击
    HTML 和 CSS 画三角形和画多边行基本原理及实践
    在线前端 JS 或 HTML 或 CSS 编写 Demo 处 JSbin 与 jsFiddle 比较
  • 原文地址:https://www.cnblogs.com/wnpp/p/15270648.html
Copyright © 2020-2023  润新知