设计模式(一):策略者、装饰者、观察者

策略者模式

使用背景:
当写好代码打包发布给别人使用时,别人如果需要对代码进行扩展,传统类封装的方式就显得十分不方便。
这时策略者模式就闪亮登场了,因为策略者模式遵循开闭原则:对修改关闭,对扩展开放。
下面是一个计算器使用策略者模式实现的例子

public class Strategy {
    /**
     * 操作接口
     */
    interface Operation{
        public int doOperation(int n,int m);
    }

    /**
     * 定义实现具体操作
     */
    class OperationAdd implements Operation{
        @Override
        public int doOperation(int n, int m) {
            return n + m;
        }
    }

    /**
     * 定义实现具体操作
     */
    class OperationSub implements Operation{
        @Override
        public int doOperation(int n, int m) {
            return n - m;
        }
    }

    /**
     * 计算器类
     */
    class Calculator{
        private Operation operation;

        public void setOperation(Operation operation) {
            this.operation = operation;
        }

        public int doOperation(int n,int m){
            return operation.doOperation(n,m);
        }
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        Strategy demo = new Strategy();
        Calculator calculator = demo.new Calculator();
        calculator.setOperation(demo.new OperationAdd());
        System.out.println(calculator.doOperation(1, 2));
    }
}
优点:

遵循了开闭原则,扩展性良好。

缺点:

随着你的策略增加,你的类也会越来越多。所有的策略类都要暴露出去,所以如果你在实际开发中使用了策略模式,一定要记得写好文档让你的伙伴们知道已有哪些策略。

装饰者模式

使用背景:当我们需要在原生类上扩展新的功能时,传统修改原生类的方式会带来很大的不便。
这时就应该使用装饰者模式对原生类进行动态的扩展。
下面就是一个装饰者模式的简单应用

public class Decorator {
    /**
     * 被装饰对象
     */
    interface Person{
        int doOperation();
        void show();
    }

    /**
     * 装饰器的超类
     */
    abstract class DecoratorPerson implements Person{
        protected Person person;

        public DecoratorPerson(Person person) {
            this.person = person;
        }
    }

    /**
     * 未被装饰前对象
     */
    class NoDecoratorPerson implements Person{
        @Override
        public int doOperation() {
            return 0;
        }

        @Override
        public void show() {
            System.out.println("未被装饰:"+this.doOperation());
        }
    }

    /**
     * A装饰后
     */
    class DecoratorPersonByA extends DecoratorPerson{
        public DecoratorPersonByA(Person person) {
            super(person);
        }

        @Override
        public int doOperation() {
            return person.doOperation() + 10;
        }

        @Override
        public void show() {
            person.show();
            System.out.println("A装饰后:"+this.doOperation());
        }
    }

    /**
     * B装饰后
     */
    class DecoratorPersonByB extends DecoratorPerson{

        public DecoratorPersonByB(Person person) {
            super(person);
        }

        @Override
        public int doOperation() {
            return person.doOperation() + 20;
        }

        @Override
        public void show() {
            person.show();
            System.out.println("B装饰后:"+this.doOperation());
        }
    }

    public static void main(String[] args) {
        Decorator demo = new Decorator();
        Person a = demo.new NoDecoratorPerson();
        a = demo.new DecoratorPersonByA(a);
        a = demo.new DecoratorPersonByB(a);
        a.show();
        System.out.println("最终:"+a.doOperation());
    }
}

通过使用装饰器接口,需要对原生类进行扩展时,便可以通过实现类装饰便可以完成对原生类的动态扩展,遵循了开闭原则。
Java 中的 IO 流便是使用了这种装饰器模式:
在这里插入图片描述
可以发现InputStream其实就是被装饰对象的超类,StringBufferInputStream等就是被装饰的对象,
FilterInputStream就是装饰器的父类,其他则是具体的装饰器。

观察者模式

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通 知并自动更新。
例子

/**
 * 观察者模式
 */
public class Observer {
    /**
     * 观察者
     */
    abstract class Customer {
        abstract void update();
    }

    /**
     * 观察者A
     */
    class CustomerA extends  Customer{
        @Override
        void update() {
            System.out.println("A收到了更新消息!!!");
        }
    }

    /**
     * 观察者B
     */
    class CustomerB extends  Customer{
        @Override
        void update() {
            System.out.println("B收到了更新消息!!!");
        }
    }

    /**
     * 基础接口
     */
    interface ISubject{
        void registerObserver(Customer customer);
        void removeObserver(Customer customer);
        void doUpdate();
    }

    /**
     * 被观察者
     */
    class BeObserved implements ISubject{
        List<Customer> customers = new ArrayList<>();
        //添加观察者
        @Override
        public void registerObserver(Customer customer) {
            this.customers.add(customer);
        }

        @Override
        public void removeObserver(Customer customer) {
            this.customers.remove(customer);
        }

        //更新消息
        @Override
        public void doUpdate(){
            for (Customer customer : customers) {
                customer.update();
            }
        }
    }

    public static void main(String[] args) {
        Observer demo = new Observer();
        Customer a = demo.new CustomerA();
        Customer b = demo.new CustomerB();
        BeObserved beObserved = demo.new BeObserved();
        beObserved.registerObserver(a);
        beObserved.registerObserver(b);
        beObserved.doUpdate();
    }
}

java原生提供了Observe和Observable两个接口用于实现观察者模式

/**
 * jdk原生的观察者模式
 */
public class ObserverByJdk {
    class CustomerA implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            System.out.println("A收到了更新!!!");
        }

    }
    class CustomerB implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            System.out.println("B收到了更新!!!");
        }

    }
    class BeObserved extends Observable{

        public void doUpdate() {
            this.setChanged();
            this.notifyObservers();
        }
    }

    public static void main(String[] args) {
        ObserverByJdk demo = new ObserverByJdk();
        Observer a = demo.new CustomerA();
        Observer b = demo.new CustomerB();
        Observable observed = demo.new BeObserved();
        observed.addObserver(b);
        observed.addObserver(a);
        ((BeObserved) observed).doUpdate();
    }
}
优点:

观察者和被观察之间抽象耦合,自有一套触发机制,被观察者无需知道通知对象是谁,只要是符合观察者接口的就可以。

缺点:

观察者只知道被观察发生变化,而无法知道是如何发生变化的,比如是修改了 name 字段还是其他,观察者都不知道。如果有很多个观察者,一个个通知比较耗时。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值