Android技术知识Java设计模式

大话设计模式——装饰模式

2017-08-09  本文已影响0人  Mr丶sorrow

需求

写一个给人模拟搭配不同服饰的程序,可以给人换各种各样的衣服裤子的形象。

初步实现

需求比较简单,直接上代码:

public class Person {
    private String name;

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

    public void wearTShirt(){
        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 Client {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("小明");

        person.wearTShirt();
        person.wearBigTrouser();
        person.wearSneakers();
        person.show();

        person.wearSuit();
        person.wearTie();
        person.wearLeatherShoes();
        person.show();
    }
}

运行结果:


程序运行结果

分析

通过前面几节的介绍,可以发现这种写法的显著毛病:难以实现功能拓展。比如现在不仅仅只有这两种搭配方式,额外需要添加其他的搭配方式,该怎么办呢?这种写法必然需要对Person类进行手术,违反了开闭原则。

改进实现

很容易结合前面的实例,我们利用面向对象的程序设计方式,通过创造服饰抽象类,让其他具体的西装、领带、垮裤等来继承,实现程序功能的可扩展。
UML类图:

UML类图

Person类实现:

public class Person {
    private String name;

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

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

服饰基类:

public abstract class Finery {
    public abstract void show();
}

其他具体衣服的实现,以大T恤、西装为例:

public class TShirt extends Finery {
    @Override
    public void show() {
        System.out.println("大T恤");
    }
}
public class Suit extends Finery {
    @Override
    public void show() {
        System.out.println("西装");
    }
}

客户端代码:

public class Client {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("小明");

        Finery xz = new Suit();
        Finery ld = new Tie();
        Finery px = new LeatherShoes();

        xz.show();
        ld.show();
        px.show();
        person.show();
    }
}

再次分析

<<大话设计模式>>49页中提及,上面这种改进方案虽然实现了服饰与人的分离,且利用面向对象程序设计的特性可以实现功能的扩展,但是仍然存在一个显著的问题——穿衣服的动作是一步一步完全暴露在外面的。

xz.show();
ld.show();
px.show();

通过在客户端,一步步的进行穿着服饰,这种设计方案是不够良好的。(但实际开发中不好在哪,我也没有深刻理解。)这些操作应该在内部组装完毕,同时也要将需要的功能(服饰)按照一定的顺序进行串联,不能先打领带后穿衬衫等...而装饰模式就是解决这一需求的。

装饰模式

装饰模式的使用

UML类图:

UML类图
这里需要注意的是,装饰模式,装饰类与被装饰类都是继承自同一父类,究竟是为什么?这一点在客户端代码中可以体现,需要好好体会,这也是理解装饰模式的关键所在。

代码实现:

  1. Component抽象类——被装饰者的抽象类,实际中也不一定有此类:

    public abstract class Component {
        public abstract void meathod();
    }
    
  2. 具体的被装饰者类:

    public class ConcreteComponent extends Component {
        @Override
        public void meathod() {
            System.out.println("具体要被装饰的对象的方法");
        }
    }
    
  3. Decorator抽象类——装饰者抽象类:

    public abstract class Decorator extends Component {
        private Component component;
    
        public void setComponent(Component component) {
            this.component = component;
        }
    
        @Override
        public void meathod() {
            if (component != null)
                component.meathod();
        }
    }
    
  4. 具体的装饰类A,B:

    public class ConcreteDecoratorA extends Decorator {
    
        private void addNewMethodOfA(){
            //A装饰器的作用
            System.out.println("A装饰器的作用");
        }
    
        @Override
        public void meathod() {
            super.meathod();
            addNewMethodOfA();
        }
    }
    
    public class ConcreteDecoratorB extends Decorator {
    
        private void addNewMethodOfB(){
            //B装饰器的作用
            System.out.println("B装饰器的作用");
        }
    
        @Override
        public void meathod() {
            super.meathod();
            addNewMethodOfB();
        }
    }
    
  5. 客户端类:

    public class Client {
    
        public static void main(String[] args) {
            Component component = new ConcreteComponent();
            Decorator decoratorA = new ConcreteDecoratorA();
            Decorator decoratorB = new ConcreteDecoratorB();
    
            decoratorA.setComponent(component);
            decoratorB.setComponent(decoratorA);
            decoratorB.meathod();
        }
    }
    

总结:

利用装饰模式实现换衣

UML类图:

UML类图

代码实现:

  1. Person类——被装饰者;

    public class Person {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void show() {
            System.out.println("装扮的" + name);
        }
    }
    
  2. Finery类——抽象装饰类;

    public abstract class Finery extends Person {
    
        private Person person;
    
        public void setPerson(Person person) {
            this.person = person;
        }
    
        @Override
        public void show() {
            if (person != null)
                person.show();
        }
    }
    
  3. 其他具体装饰类;

    public class BigTrousers extends Finery {
        @Override
        public void show() {
            super.show();
            System.out.println("垮裤");
        }
    }
    
  4. 客户端类;

    public class Client {
        public static void main(String[] args) {
            Person person = new Person();
            person.setName("小明");
    
            Finery xz = new Suit();
            Finery ld = new Tie();
            Finery px = new LeatherShoes();
    
            xz.setPerson(person);
            ld.setPerson(xz);
            px.setPerson(ld);
            px.show();
        }
    }
    
  5. 运行结果:


    运行结果

装饰模式小结

上一篇 下一篇

猜你喜欢

热点阅读