设计模式(装饰者模式、模板方法、观察者模式、适配器模式、策略模式)

目录装饰者模式模板方法模式观察者模式适配器模式类适配器模式对象适配器模式策略模式 装饰者模式 装饰(Decorator)模式的定义:指在不改变现有对象结构的情

装饰者模式

装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额

外功能)的模式,它属于对象结构型模式。

装饰(Decorator)模式的主要优点有:

  • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
  • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

星巴克咖啡的案例

package org.westos.decorator;

/**
 * @author lwj
 * @date 2020/6/9 13:02
 */
public abstract class Drink {
    public String description;
    private double price;

    public String getDescription() {
        return description;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    //计算费用的抽象方法
    public abstract double cost();
}
package org.westos.decorator;

/**
 * @author lwj
 * @date 2020/6/9 13:13
 */
public class Coffee extends Drink {
    @Override
    public double cost() {
        return super.getPrice();
    }
}

class Espresso extends Coffee {
    public Espresso() {
        this.description = "意大利咖啡";
        //构造方法,初始化成员变量
        this.setPrice(20.0);
    }
}

class BlackCoffee extends Coffee {
    public BlackCoffee() {
        this.description = "黑咖啡";
        this.setPrice(25.0);
    }
}

装饰者

package org.westos.decorator;

/**
 * 装饰类
 * @author lwj
 * @date 2020/6/9 13:21
 */
public class Decorator extends Drink {
    private Drink coffee;
    //被装饰的饮料

    public Decorator(Drink coffee) {
        this.coffee = coffee;
    }

    @Override
    public double cost() {
        return super.getPrice() + coffee.cost();
    }

    @Override
    public String getDescription() {
        //重写父类的方法,别想着this,只有super,因为如果是this的话,那么就变成了无穷递归下去,到最后堆栈溢出
        return super.getDescription() + "[" + coffee.getDescription() + "]";
    }
}

class Chocolate extends Decorator {

    public Chocolate(Drink coffee) {
        super(coffee);
        this.description = "巧克力";
        this.setPrice(10.0);
    }
}

class Milk extends Decorator {

    public Milk(Drink coffee) {
        super(coffee);
        this.description = "牛奶";
        this.setPrice(5.0);
    }
}

测试类

package org.westos.decorator;

/**
 * @author lwj
 * @date 2020/6/9 13:47
 */
public class MyTest {
    public static void main(String[] args) {
        //装饰者模式下的订单:2份巧克力,一份加奶的意大利咖啡
        Espresso espresso = new Espresso();
        System.out.println(espresso.getDescription());
        //意大利咖啡
        System.out.println(espresso.cost());
        //20.0

        Milk milk = new Milk(espresso);
        System.out.println(milk.getDescription());
        //牛奶[意大利咖啡]
        System.out.println(milk.cost());
        //25.0

        Chocolate chocolate = new Chocolate(new Chocolate(milk));
        System.out.println(chocolate.getDescription());
        //巧克力[巧克力[牛奶[意大利咖啡]]]
        System.out.println(chocolate.cost());
        //45.0
    }
}

关于面向对象中的继承重写

package org.westos.test;

/**
 * @author lwj
 * @date 2020/6/9 13:57
 */
public class SuperClass {
    private String description;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

class SubClass extends SuperClass {
    public SubClass() {
        this.setDescription("子类");
    }

    @Override
    public String getDescription() {
        return super.getDescription();
        //并不是说调用super.getDescription()打印的属性就为null了,重写只是为了在默认的输出上加上额外的东西
        //return this.getDescription();
    }
}

class Test {
    public static void main(String[] args) {
        System.out.println(new SubClass().getDescription());
        //子类
    }
}

模板方法模式

模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类

中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

该模式的主要优点如下。

  1. 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
  2. 它在父类中提取了公共的部分代码,便于代码复用。
  3. 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
package org.westos.templatemethod;

/**
 * @author lwj
 * @date 2020/6/9 14:21
 */
public abstract class AbstractClass {
    public void templateMethod() {
        specificMethod();
        abstractMethod1();
        abstractMethod2();
    }

    public void specificMethod() {
        System.out.println("抽象类中的具体方法被调用");
    }

    public abstract void abstractMethod1();

    public abstract void abstractMethod2();
}

class ConcreteClass extends AbstractClass {

    @Override
    public void abstractMethod1() {
        System.out.println("抽象方法1的实现被调用");
    }

    @Override
    public void abstractMethod2() {
        System.out.println("抽象方法2的实现被调用");
    }
}

测试类

package org.westos.templatemethod;

/**
 * @author lwj
 * @date 2020/6/9 14:24
 */
public class MyTest {
    public static void main(String[] args) {
        AbstractClass abstractClass = new ConcreteClass();
        abstractClass.templateMethod();
        //抽象类中的具体方法被调用
        //抽象方法1的实现被调用
        //抽象方法2的实现被调用
    }
}

观察者模式

观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象(Subject)的状态发生改变

时,所有依赖于它的对象(Observer)都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图

模式,它是对象行为型模式。

Subject目标对象

package org.westos.observer;


import java.util.LinkedList;
import java.util.List;

/**
 * @author lwj
 * @date 2020/6/9 14:34
 */
public class Subject {
    private List<Observer> observers = new LinkedList<>();

    public void setMsg(String msg) {
        notifyObservers(msg);
    }

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers(String msg) {
        for (Observer observer : observers) {
            observer.update(msg);
        }
    }
}

观察者对象

package org.westos.observer;

/**
 * @author lwj
 * @date 2020/6/9 14:35
 */
public abstract class Observer {
    //观察者对象
    public abstract void update(String msg);
}

class ConcreteObserver1 extends Observer {

    @Override
    public void update(String msg) {
        System.out.println(this.getClass().getName() + "---" + msg);
    }
}

class ConcreteObserver2 extends Observer {

    @Override
    public void update(String msg) {
        System.out.println(ConcreteObserver2.class.getName() + "---" + msg);
    }
}

测试类

package org.westos.observer;

/**
 * @author lwj
 * @date 2020/6/9 15:38
 */
public class MyTest {
    public static void main(String[] args) {
        ConcreteObserver1 observer1 = new ConcreteObserver1();
        ConcreteObserver2 observer2 = new ConcreteObserver2();

        Subject subject = new Subject();
        subject.addObserver(observer1);
        subject.addObserver(observer2);

        subject.setMsg("天气转凉,请注意加衣。");
        
        //org.westos.observer.ConcreteObserver1---天气转凉,请注意加衣。
        //org.westos.observer.ConcreteObserver2---天气转凉,请注意加衣。
    }
}

适配器模式

适配器模式分为类适配器模式和对象适配器模式。

类适配器模式

package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:33
 */
public interface Target {
    void request();
}
package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:34
 */
public class Adaptee {
    public void specificRequest() {
        System.out.println("适配者中的业务代码被调用");
    }
}
package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:35
 */
public class ClassAdapter extends Adaptee implements Target{
    @Override
    public void request() {
        specificRequest();
    }
}

测试类

package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:36
 */
public class MyTest {
    public static void main(String[] args) {
        Target target = new ClassAdapter();
        target.request();
        //类适配器模式,继承了Adaptee的方法
        //适配者中的业务代码被调用
    }
}

对象适配器模式

package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:48
 */
public class ObjectAdapter implements Target {
    private Adaptee adaptee;

    public ObjectAdapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}

测试类

package org.westos.adapter;

/**
 * @author lwj
 * @date 2020/6/9 18:49
 */
public class MyDemo {
    public static void main(String[] args) {
        Target target = new ObjectAdapter(new Adaptee());
        target.request();
        //适配者中的业务代码被调用
    }
}

策略模式

策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法

的变化不会影响使用算法的客户。策略模式属于对象行为模式。

package org.westos.strategy;

/**
 * @author lwj
 * @date 2020/6/9 18:54
 */
public interface Strategy {
    int doOperation(int num1, int num2);
}

class OperationAdd implements Strategy {

    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

class OperationSubtract implements Strategy {

    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

class OperationMultiply implements Strategy {

    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}
package org.westos.strategy;

/**
 * @author lwj
 * @date 2020/6/9 18:57
 */
public class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

测试类

package org.westos.strategy;

/**
 * @author lwj
 * @date 2020/6/9 18:59
 */
public class MyTest {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        System.out.println(context.executeStrategy(12, 13));
        //25

        Context context1 = new Context(new OperationSubtract());
        System.out.println(context1.executeStrategy(12, 13));
        //-1

        Context context2 = new Context(new OperationMultiply());
        System.out.println(context2.executeStrategy(12, 13));
        //156
    }
}