head first 设计模式笔记

设计模式

策略模式

定义

策略模式定义了算法簇,分别封装,让他们可以互相替换,次模式将算法独立于使用算法的客户

思想

  1. 多组合,少继承
  2. 针对接口编程,而不是针对实现编程
  3. 将变化代码,公用代码分离
  4. 核心思想是组合不同接口的实现,将接口定义到超类的变量中,通过构造函数或者方法来修改实现类,进而修改其行为。松耦合、可组合

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public Duck() {
    }

    public void setFlyBehavior(FlyBehavior fb) {
        flyBehavior = fb;
    }

    public void setQuackBehavior(QuackBehavior qb) {
        quackBehavior = qb;
    }

    abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
}

观察者模式

定义

类似队列的广播模式,publish–>consumer,object–>observe,需观察者注册到主题,主题发生变化,通知观察者

思想

将观察者和主题松耦合,观察者改变不影响主题。可以有多个观察者,观察者可以自由订阅、取消。随着服务从一体集成到分布式。观察者模式很少使用,取而代之的是消息中间件。

public interface Subject {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();
}

public interface Observer {
    public void update(float temp, float humidity, float pressure);
}

装饰者模式

定义

思想

对扩展开放,对修改关闭,俗称开闭原则。通过继承来修改,不可以直接修改该类型。
通过扩展父类的方法,来实现装饰。如下LowCaseInputStream,通过重写父类read方法来实现装饰。装饰者模式有个小小的缺点,实现类会比较多,容易让人混乱,需要找到被装饰类。对理解帮助很大

简单、抽象工厂模式

简单工厂:将对象的创建抽象出来,通过工厂统一管理对象的创建
抽象工厂:将对象的创建移动至实现抽象工厂的对象中

思想

面向接口编程,不依赖具体的实现,依赖倒置

public class SimplePizzaFactory {

    public Pizza createPizza(String type) {
        Pizza pizza = null;

        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        } else if (type.equals("clam")) {
            pizza = new ClamPizza();
        } else if (type.equals("veggie")) {
            pizza = new VeggiePizza();
        }
        return pizza;
    }
}

public interface PizzaAbstractFactory {

    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();

}

单例模式

在一些场景全局只使用一个对象如:线程池、连接池、缓存
启动时加载:加载类是初始化对象,优点:简单 缺点:占用、浪费资源,有可能一致未使用,但是已加载
延迟加载(同步锁):getInstance 增加同步锁 优点:安全 缺点:性能差
延迟加载,双重锁校验(DCL):关键字voliate + sync 关键字

public class Singleton {
    private static Singleton uniqueInstance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return uniqueInstance;
    }

    // other useful methods here
    public String getDescription() {
        return "I'm a statically initialized Singleton!";
    }
}

public class Singleton {
    protected static Singleton uniqueInstance;

    // other useful instance variables here

    protected Singleton() {}

    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

    // other useful methods here
}

public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

命令模式

将请求封装为对象,可以使用不同的请求、日志来参数化对象

适配器模式、外观模式

适配器模式

通过adapter 实现target,通过adapter调用adaptee(源角色)实现适配。
使用场景:新旧功能、系统之间相互兼容、适配

外观模式

将复杂操作封装一起,对外简介
使用场景:简化代码,对外保持简单

模板方法

模板方法定义了一个或一组执行动作,由子类实现一个或多个步骤。
使用场景,抽象出一套骨架,具体业务实现骨架中的具体方法。采用继承抽象类方式。
对比策略模式:策略模式更注重组合的方式,相对灵活。模板方式更适用于规范

public abstract class CaffeineBeverageWithHook {

    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    abstract void brew();

    abstract void addCondiments();

    void boilWater() {
        System.out.println("Boiling water");
    }

    void pourInCup() {
        System.out.println("Pouring into cup");
    }

    boolean customerWantsCondiments() {
        return true;
    }
}

迭代器

迭代器和模板有些类似,定义一个接口,实现接口中的方法,即可进行相关的next hasnext操作。
可以参考java 中的Iterator 接口

组合模式

定义:
可以支持某种数据结构,通过类的组合,构造所需的数据结构,一个典型的场景是树形结构
定义一个组件MenuComponent(主节点)、菜单最小单元(叶子节点)、菜单(中间节点)

public abstract class MenuComponent {

    public void add(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public void remove(MenuComponent menuComponent) {
        throw new UnsupportedOperationException();
    }

    public MenuComponent getChild(int i) {
        throw new UnsupportedOperationException();
    }

    public String getName() {
        throw new UnsupportedOperationException();
    }

    public String getDescription() {
        throw new UnsupportedOperationException();
    }

    public double getPrice() {
        throw new UnsupportedOperationException();
    }

    public boolean isVegetarian() {
        throw new UnsupportedOperationException();
    }

    public void print() {
        throw new UnsupportedOperationException();
    }
}


@Data
public class MenuItem extends MenuComponent {
    String name;
    String description;
    boolean vegetarian;
    double price;

    public void print() {
        System.out.print("  " + getName());
        if (isVegetarian()) {
            System.out.print("(v)");
        }
        System.out.println(", " + getPrice());
        System.out.println("     -- " + getDescription());
    }
}

public class Menu extends MenuComponent {
    ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
    String name;
    String description;

    public void add(MenuComponent menuComponent) {
        menuComponents.add(menuComponent);
    }

    public void remove(MenuComponent menuComponent) {
        menuComponents.remove(menuComponent);
    }

    public MenuComponent getChild(int i) {
        return (MenuComponent) menuComponents.get(i);
    }

    public void print() {
        System.out.print("\n" + getName());
        System.out.println(", " + getDescription());
        System.out.println("---------------------");

        Iterator<MenuComponent> iterator = menuComponents.iterator();
        while (iterator.hasNext()) {
            MenuComponent menuComponent = (MenuComponent) iterator.next();
            menuComponent.print();
        }
    }
}

状态机模式

定义

状态(state)
事件(Event)
通过定义state实现状态基类的方法,从而实现该状态针对各个Event的处理并转变当前状态

思想

状态机模式,管理状态的流转,及该状态可执行的事件,解决了 if else 和 switch 判断较多问题 ,state — >event—>state1
针对状态遵守了开闭原则,但是针对事件不适合。

代理模式

定义

为另一个对象提供一个替身或者占位符控制这个对象的访问,对用户透明。for example : rmi、dubbo、sping aop

思想

对用户透明