设计模式 -个人笔记

教程资料:
http://c.biancheng.net/design_pattern/

概述:

学习设计模式,开阔思路,在架构设计上起作用。
正常的开发代码,只是一种流程,短时期不会出问题,但是长时间的话,则需要提前

设计原则:

1,开闭原则

软件实体应当对扩展开放,对修改关闭。

简单的说,设计的的对象,要考虑今后的扩展性,尽量保证未来出现新需求,或者变化时,尽量减少对对象本身的修改。
这点基本上没什么异议,修改的影响不好估计,最好还是进行最小变动,不改变原对象,而是需要修改的地方自行打补丁即可。

2,里氏替换原则

继承必须确保超类所拥有的性质在子类中仍然成立。

通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。
java中的重写就是覆盖父类的方法进行实现,这是正常的功能,但是使用的时候需要注意,比如void open()的方法,改成了关闭的操作,那么之后的使用人就很容易出错。因此需要注意。

3,依赖倒置原则

高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

其核心思想是:要面向接口编程,不要面向实现编程。
也就是说,在设计的时候的思想要考虑的是创建一个对象,去设计这个对象要做的应做到的事情,而不是一直考虑需求。最终设计出的对象,应该是从父到子,一级级继承下来,且为了扩展,而继承最初模型的抽象。

4,单一职责原则

规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。

该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:

  1. 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
  2. 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。
    实际上就是设计的尽量拆分的想法,比如一辆车概念太大,就划分成发动机,地盘,轮胎等等

5,接口隔离原则

要求程序员尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。

接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者是不同的:

  1. 单一职责原则注重的是职责,而接口隔离原则注重的是对接口依赖的隔离。
  2. 单一职责原则主要是约束类,它针对的是程序中的实现和细节;接口隔离原则主要约束接口,主要针对抽象和程序整体框架的构建。
    类的实现可以实现多个接口,那么就把接口拆分,尽量解耦。

6,迪米特法则

又叫作最少知识原则,定义是只与你的直接朋友交谈,不跟“陌生人”说话。其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

简单的说,一个对象想要扩展功能,实现和自己本身不相干的事物的时候的,不建议修改自身进行实现,而是使用其他对象,专门负责本对象和功能的实现。类似明细和经纪人的关系。

7,合成复用原则

软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

复用,即一个对象用着不同的情况下,适应不同的需求。这个原则举例来说,手机有华为小米的,2核4核的,4G5G的,以上3个属性,如果使用继承的方式创建对象的话,需要2 X 2 X 2 = 8的的对象。而如果使用组合,3个属性都是【手机】这个对象的属性的话,只需要一个对象就可以了。

设计模式种类(Gof的23种):

编号 名称 英文 分类 标签 个人简述
1 单例 Singleton 创建 共享对象 一个类共享一个对象
2 原型 Prototype 创建 克隆对象 复制自身
3 工厂 Factory 创建 工厂对象 先建立工厂,再用工厂创建对象,创建和使用分离
4 抽象工厂 AbstractFactory 创建 属性抽象 种类抽象,多继承的方式,使得一个工厂生产不同的东西
5 建造者 AbstractFactory 创建 多个建造者组合复杂对象 指挥者整合建造者,然后逐步调用,生产产品
6 代理 Proxy 调用 间接调用 通过调用代理调用对象,主要用于扩展
7 适配器 Adapter 调用 间接调用 继承方式实现,关联2个对象
8 桥接 Bridge 调用 间接调用 将抽象与实现分离,关键是组合的方式实现
9 装饰 Decorator 调用 追加处理 继承的方式,追加处理内容
10 外观 Facade 组合 内部对象 第三方熟悉放置在对象内,对象内调用执行
11 享元 Flyweight 组合 内部对象 外观是直接放置,01,02,03的对象,享元是Map
12 组合 Composite 组合 部分-整体 树状层次结构,使用户对单个对象和组合对象具有一致的访问性
13 模板 Template 模板 模板骨架 制作一个不完全的模板,子类实现
14 策略 Strategy 选择执行 switch 根据请求关键字,不同情况执行不同对象
15 命令 Command 调用分离 执行-调用分离 实现者/接收者/调用者/请求者,全部单独调用
16 职责链 Chain of Responsibility 选择执行 链表+if 根据请求关键字,不同情况执行不同对象
17 状态 State 内部属性 动态属性 对象内部属性,根据不同情况执行不同对象
18 观察者 Observer 内部属性 触发器 对象变化时,触发对观察者的通知
19 中介者 Mediator 内部属性 触发器 对象作为中介,链接不同对象,并且相互触发
20 迭代器 Iterator 内部属性 迭代器 类似指针或者迭代器,按照顺序访问
21 访问者 Visitor 内部属性 追加处理内容 将数据操作和数据结构分离,访问者是执行内容
22 备忘录 Memento 附加功能 备份器 对象的备份
23 解释器 Interpreter 附加功能 解释器 根据A的值,解释器含义

个人总结:

  • 单例,原型,工厂,抽象工厂,建造者都是完全的一种东西的创建方法。用于创建对象。
  • 代理,适配器,桥接,装饰都是将不同的对象或者方法进行拼接的方式,组合成新功能的对象。
  • 外观,享元,组合是整合用的对象,将类似或者相同的对象整合在一起,方便使用。

设计模式详细:

-------------------------------- 创建型模式 --------------------------------

1,单例模式【重要】

指一个类只有一个实例,且该类能自行创建这个实例的一种模式。

算是最常用的设计模式,相对与一般类对象使用new创建,每次都分配一次空间来说,单例就是一次创建,多次使用。
经典的单例分为以下2种:

  1. 懒汉式单例:类加载时不创建对象,第一次使用时才创建。 【常用】
  2. 饿汉式单例:类加载时就创建对象,每次使用时调用。
    spring,单例模式等广泛应用。

简单的实现:
主要以下代码中,核心的数据使用了static,这就保证了对象数据的共享。

/**
 * 懒汉式单例
 * 加载时不创建,使用时创建
 */
public class LazySingleton {
    private static LazySingleton data; // 模拟核心数据
    public LazySingleton(){}
    // 数据使用时的方法
    public LazySingleton getInstance(){
        if(null == data){
            data = new LazySingleton(); // new对象
        }
        return data;
    }
}

/**
 * 饿汗式单例
 * 加载时创建,使用调用
 */
public class HungrySingleton {
    private static final HungrySingleton data = new HungrySingleton(); // 类加载时创建
    public HungrySingleton(){}
    // 数据使用时的方法
    public HungrySingleton getInstance(){
        return data;
    }
}

需要注意的是,在多线程中的使用,饿汉式单例因为是类加载时创建,基本不会有多线程的问题。但是懒汉式的对象,如果初次调用时是在多线程的环境里,就有可能产生多线程的问题,所以一般进行如下改造:

/**
 * 懒汉式单例 -- 线程安全
 * 加载时不创建,使用时创建
 * 同时考虑线程安全的问题
 */
public class LazySingletonSafe {
    private static volatile LazySingletonSafe data; // 模拟核心数据
    public LazySingletonSafe(){}
    // 数据使用时的方法
    public LazySingletonSafe getInstance(){
        if(null == data){
            synchronized(LazySingletonSafe.class){
                if(null == data){
                    data = new LazySingletonSafe(); // new对象
                }
            }
        }
        return data;
    }
}

2,原型模式

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
简单的说,就是先建个范本,然后继承Cloneable,使用克隆的方式创建。

复制自身,这种方法很少用。也就是创建对象本身消耗较大时使用。

/**
 * 原型模式
 */
public class Realizetype implements Cloneable {
    public Realizetype(){
        System.out.println("初始化");
    }
    @Override
    protected Object clone() throws CloneNotSupportedException { // 克隆用对象
        return super.clone();
    }
}
/**
 * 测试
 */
public static void main(String[] args) throws CloneNotSupportedException {
    Realizetype realizetype = new Realizetype();
    Realizetype new_realizetype = (Realizetype) realizetype.clone();
    // 结果是:【obj1==obj2?false】
    System.out.println("obj1==obj2?"+(realizetype==new_realizetype));
}

3,工厂模式

定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

创建工厂,然后使用工厂创建对象。问题在于如果对象比较多的时候,需要进行扩展的时候,对工厂就不方便了,直接修改工厂不符合开闭原则,一个类型一个工厂又很麻烦。

/**
 * 测试的工厂
 */ 
interface Car {
    public String getName();
}
class  Wuling implements Car{
    @Override
    public String getName() {
        return "五菱";
    }
}
class Tesile implements Car{
    @Override
    public String getName() {
        return "特斯拉";
    }
}

/**
 * 工厂类
 */
class CarFactory{
    public Car getCar(String key) {
        if ("五菱".equals(key)) {
            return new Wuling();
        } else if ("特斯拉".equals(key)) {
            return new Tesile();
        }
        return null;
    }
}

4,抽象工厂模式

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构

是工厂模式的升级版本,简单的说,工厂模式适用于只生产一种或者一类物品。而抽象工厂则是包含了不同种类的物品。
举例来说,生产电脑要生产很多不同的东西,比如显示器,主机,CPU等,有不同的厂家,如苹果,戴尔。则生产电脑的概念为抽象工厂类。具体的厂商则为具体的工厂实现类。

image

image

5,建造者模式

指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

使用【指挥者-建造者】的方式,使用指挥者装载建造者进行创建对象,就像是同规格的不同【建造者】子弹,都可使用【指挥者】手枪来发射,来打出子弹。

代码例子:

/**
 * 产品对象
 */
public class Phone {
    private String partScreen;
    private String partCell;
    private String partCpu;
    public void setPartScreen(String partScreen) {
        this.partScreen = partScreen;
    }
    public void setPartCell(String partCell) {
        this.partCell = partCell;
    }
    public void setPartCpu(String partCpu) {
        this.partCpu = partCpu;
    }
    public String show() {
        return "Product{" +
                "partScreen='" + partScreen + '\'' +
                ", partCell='" + partCell + '\'' +
                ", partCpu='" + partCpu + '\'' +
                '}';
    }
}
/**
 * 抽象建造者
 */
public abstract class Builder {
    //创建产品对象
    protected Phone phone = new Phone();
    public abstract void buildPartScreen();
    public abstract void buildPartCell();
    public abstract void buildPartCpu();
    //返回产品对象
    public Phone getResult()
    {
        return phone;
    }
}
public class HuaweiBuilder extends Builder {
    @Override
    public void buildPartScreen() {
        phone.setPartScreen("屏幕:6.57英寸");
    }
    @Override
    public void buildPartCell() {
        phone.setPartCell("电池:4000mAh");
    }
    @Override
    public void buildPartCpu() {
        phone.setPartCpu("海思 麒麟985");
    }
}
public class MilletBuilder extends Builder {
    @Override
    public void buildPartScreen() {
        phone.setPartScreen("屏幕:6.67英寸");
    }
    @Override
    public void buildPartCell() {
        phone.setPartCell("电池:4780mAh");
    }
    @Override
    public void buildPartCpu() {
        phone.setPartCpu("高通 骁龙865");
    }
}
/**
 * 指挥类-组织装者
 */
public class Director {
    private Builder builder;
    // 创建对象的时候搭载
    public Director(Builder builder) {
        this.builder = builder;
    }
    //产品构建与组装方法
    public Phone construct() {
        builder.buildPartCell();
        builder.buildPartCpu();
        builder.buildPartScreen();
        return builder.getResult();
    }
}
/**
 * 客户类,测试
 */
public class Client {
    public static void main(String[] args) {
        Phone phoneA = new Director(new HuaweiBuilder()).construct();
        System.out.println(phoneA.show());
        // -------------------------------------------------------
        Phone phoneB = new Director(new MilletBuilder()).construct();
        System.out.println(phoneB.show());

        // 结果
        // Product{partScreen='屏幕:6.57英寸', partCell='电池:4000mAh', partCpu='海思 麒麟985'}
        // Product{partScreen='屏幕:6.67英寸', partCell='电池:4780mAh', partCpu='高通 骁龙865'}
    }
}

-------------------------------- 结构型模式 --------------------------------

1,代理模式【常见】

由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

像是spring的拦截器,对请求的前后处理,或者一些注解的处理。实际是调用代理对象来执行目标的处理。但在框架中,结合反射等处理,可以方便的处理。

代码例子:

public class ProxyTest {
    public static void main(String[] args) {
        Proxy proxy = new Proxy(new RealSubject());
        proxy.Request();
    }
}

//抽象-处理目标
interface Subject {
    void Request();
}
//真实-处理目标
class RealSubject implements Subject {
    @Override
    public void Request() {
        System.out.println("访问真实主题方法...");
    }
}

//代理
class Proxy implements Subject {
    private RealSubject realSubject;
    // 构造方法
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    @Override
    public void Request() {
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest() { // 代理前置
        System.out.println("访问真实主题之前的预处理。");
    }
    public void postRequest() { // 代理后置
        System.out.println("访问真实主题之后的后续处理。");
    }
}

2,适配器模式

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

所谓适配器,顾名思义就是联通A与B直接,使得原本无法连接的两者连接起来。
如下例子,Adaptee对象和Target接口本身没有关联,但是通过ClassAdapter配适器,将二者连接起来了。

代码例子:

//目标接口
interface Target {
    public void request();
}

//适配者对象
class Adaptee {
    public void specificRequest() {
        System.out.println("适配者中的业务代码被调用!");
    }
}
//类适配器类
class ClassAdapter extends Adaptee implements Target {
    public void request() {
        specificRequest();
    }
}
//客户端代码
public class ClassAdapterTest {
    public static void main(String[] args) {
        System.out.println("类适配器模式测试:");
        Target target = new ClassAdapter();
        target.request();
    }
}

3,桥接模式

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

代码例子:

/**
 * 测试类
 */
public class BridgeTest {
    public static void main(String[] args) {
        Abstraction abs = new RefinedAbstraction(new ConcreteImplementorA());
        abs.Operation();
    }
}

// 实现化角色
interface Implementor {
    public void OperationImpl();
}

// 具体实现化角色
class ConcreteImplementorA implements Implementor {
    public void OperationImpl() {
        System.out.println("具体实现化(Concrete Implementor)角色被访问");
    }
}

// 抽象化角色
abstract class Abstraction {
    protected Implementor imple;

    protected Abstraction(Implementor imple) {
        this.imple = imple;
    }

    public abstract void Operation();
}

// 扩展抽象化角色
class RefinedAbstraction extends Abstraction {
    protected RefinedAbstraction(Implementor imple) {
        super(imple);
    }

    public void Operation() {
        System.out.println("扩展抽象化(Refined Abstraction)角色被访问");
        imple.OperationImpl();
    }
}

4,装饰模式

指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

代码例子:

public class DecoratorPattern {
    public static void main(String[] args) {
        Component p = new ConcreteComponent();
        p.operation();
        System.out.println("---------------------------------");
        Component d = new ConcreteDecorator(p);
        d.operation();
    }
}

//抽象构件角色
interface Component {
    public void operation();
}

//具体构件角色
class ConcreteComponent implements Component {
    public ConcreteComponent() {
        System.out.println("创建具体构件角色");
    }

    public void operation() {
        System.out.println("调用具体构件角色的方法operation()");
    }
}

//抽象装饰角色
class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

//具体装饰角色
class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        addedFunction();
    }

    public void addedFunction() {
        System.out.println("为具体构件角色增加额外的功能addedFunction()");
    }
}

5,外观模式

是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

合并统一用接口。

代码例子:

public class DecoratorPattern {
    public static void main(String[] args) {
        Component p = new ConcreteComponent();
        p.operation();
        System.out.println("---------------------------------");
        Component d = new ConcreteDecorator(p);
        d.operation();
    }
}

//抽象构件角色
interface Component {
    public void operation();
}

//具体构件角色
class ConcreteComponent implements Component {
    public ConcreteComponent() {
        System.out.println("创建具体构件角色");
    }

    public void operation() {
        System.out.println("调用具体构件角色的方法operation()");
    }
}

//抽象装饰角色
class Decorator implements Component {
    private Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    public void operation() {
        component.operation();
    }
}

//具体装饰角色
class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        addedFunction();
    }

    public void addedFunction() {
        System.out.println("为具体构件角色增加额外的功能addedFunction()");
    }
}

6,享元模式

运用共享技术来有効地支持大量细粒度对象的复用。它通过共享已经存在的又橡来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

合并统一用接口。

package design.flyweight;

import java.util.HashMap;

public class FlyweightPattern {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight f01 = factory.getFlyweight("a");
        Flyweight f02 = factory.getFlyweight("a");
        Flyweight f03 = factory.getFlyweight("a");
        Flyweight f11 = factory.getFlyweight("b");
        Flyweight f12 = factory.getFlyweight("b");
        f01.operation(new UnsharedConcreteFlyweight("第1次调用a。"));
        f02.operation(new UnsharedConcreteFlyweight("第2次调用a。"));
        f03.operation(new UnsharedConcreteFlyweight("第3次调用a。"));
        f11.operation(new UnsharedConcreteFlyweight("第1次调用b。"));
        f12.operation(new UnsharedConcreteFlyweight("第2次调用b。"));
    }
}

//非享元角色
class UnsharedConcreteFlyweight {
    private String info;

    UnsharedConcreteFlyweight(String info) {
        this.info = info;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}

//抽象享元角色
interface Flyweight {
    public void operation(UnsharedConcreteFlyweight state);
}

//具体享元角色
class ConcreteFlyweight implements Flyweight {
    private String key;

    ConcreteFlyweight(String key) {
        this.key = key;
        System.out.println("具体享元" + key + "被创建!");
    }

    public void operation(UnsharedConcreteFlyweight outState) {
        System.out.print("具体享元" + key + "被调用,");
        System.out.println("非享元信息是:" + outState.getInfo());
    }
}

//享元工厂角色
class FlyweightFactory {
    private HashMap<String, Flyweight> flyweights = new HashMap<String, Flyweight>();

    public Flyweight getFlyweight(String key) {
        Flyweight flyweight = (Flyweight) flyweights.get(key);
        if (flyweight != null) {
            System.out.println("具体享元" + key + "已经存在,被成功获取!");
        } else {
            flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
        }
        return flyweight;
    }
}

7,组合模式

有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。

代码例子:

public class CompositePattern {
    public static void main(String[] args) {
        Component c0 = new Composite();
        Component c1 = new Composite();
        Component leaf1 = new Leaf("1");
        Component leaf2 = new Leaf("2");
        Component leaf3 = new Leaf("3");
        c0.add(leaf1);
        c0.add(c1);
        c1.add(leaf2);
        c1.add(leaf3);
        c0.operation();
    }
}

//抽象构件
interface Component {
    public void add(Component c);

    public void remove(Component c);

    public Component getChild(int i);

    public void operation();
}

//树叶构件
class Leaf implements Component {
    private String name;

    public Leaf(String name) {
        this.name = name;
    }

    public void add(Component c) {
    }

    public void remove(Component c) {
    }

    public Component getChild(int i) {
        return null;
    }

    public void operation() {
        System.out.println("树叶" + name + ":被访问!");
    }
}

//树枝构件
class Composite implements Component {
    private ArrayList<Component> children = new ArrayList<Component>();
    public void add(Component c) {
        children.add(c);
    }
    public void remove(Component c) {
        children.remove(c);
    }
    public Component getChild(int i) {
        return children.get(i);
    }
    public void operation() {
        for (Object obj : children) {
            ((Component) obj).operation();
        }
    }
}

-------------------------------- 行为型模式 --------------------------------

1,模板模式(Template Method)

定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

简单的说使用抽象类定义模板,实现部分,留下部分让子实现类进行实现。

public class TemplateMethodPattern {
    public static void main(String[] args) {
        AbstractClass tm = new ConcreteClass();
        tm.TemplateMethod();
    }
}

//抽象类
abstract class AbstractClass {
    public void TemplateMethod() //模板方法
    {
        SpecificMethod();
        abstractMethod1();
        abstractMethod2();
    }

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

    public abstract void abstractMethod1(); //抽象方法1

    public abstract void abstractMethod2(); //抽象方法2
}

//具体子类
class ConcreteClass extends AbstractClass {
    public void abstractMethod1() {
        System.out.println("抽象方法1的实现被调用...");
    }
    public void abstractMethod2() {
        System.out.println("抽象方法2的实现被调用...");
    }
}

2,策略模式【常见】(Strategy)

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

同样执行一个方法,在不同情况下执行不同处理,返回相同对象。
实际业务逻辑中有很多类似的需求,比如一个支付项目,根据请求的参数,调用不同的支付方式,微信,支付宝,或者其他。

public class StrategyPattern {
    public static void main(String[] args) {
        Context c = new Context();
        
        c.setStrategy(new ConcreteStrategyA()); // 装载A类
        c.strategyMethod();
        System.out.println("-----------------");
        c.setStrategy(new ConcreteStrategyB()); // 装载B类
        c.strategyMethod();
    }
}

//抽象策略类
interface Strategy {
    public void strategyMethod();    //策略方法
}

//具体策略类A
class ConcreteStrategyA implements Strategy {
    public void strategyMethod() {
        System.out.println("具体策略A的策略方法被访问!");
    }
}

//具体策略类B
class ConcreteStrategyB implements Strategy {
    public void strategyMethod() {
        System.out.println("具体策略B的策略方法被访问!");
    }
}

//环境类
class Context {
    private Strategy strategy;

    public Strategy getStrategy() {
        return strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void strategyMethod() {
        strategy.strategyMethod();
    }
}

3,命令模式(Command)

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

执行者和执行命令分成2个对象,这样执行者是固定的,执行命令根据不同的情况。
实际上和上边的策略模式类似,只是执行的时候,不会对象本身执行,而是使用执行者进行执行命令。

public class CommandPattern {
    public static void main(String[] args) {
        Command cmd = new ConcreteCommand();
        Invoker ir = new Invoker(cmd);
        System.out.println("客户访问调用者的call()方法...");
        ir.call();
    }
}
//调用者
class Invoker {
    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void call() {
        System.out.println("调用者执行命令command...");
        command.execute();
    }
}
//抽象命令
interface Command {
    public abstract void execute();
}
//具体命令 - 根据不同情况有不同的实现,都使用执行者进行执行
class ConcreteCommand implements Command {
    private Receiver receiver;
    ConcreteCommand() {
        receiver = new Receiver();
    }
    public void execute() {
        receiver.action();
    }
}
//接收者
class Receiver {
    public void action() {
        System.out.println("接收者的action()方法被调用...");
    }
}

4,责任链模式(Chain of Responsibility)

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

说白了,其实就像是【switch选择】形式变为【链表+if】,将可执行的对象A,B,C等,以链表的形式关联起来。然后从最开始的A开始,判断执行条件符合则执行,不符合在下一个判断,到B,同样的判断处理。

public class ChainOfResponsibilityPattern {
    public static void main(String[] args) {
        //组装责任链
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        handler1.setNext(handler2);
        //提交请求
        handler1.handleRequest("two");
    }
}

//抽象处理者角色
abstract class Handler {
    private Handler next;

    public void setNext(Handler next) {
        this.next = next;
    }

    public Handler getNext() {
        return next;
    }

    //处理请求的方法
    public abstract void handleRequest(String request);
}

//具体处理者角色1
class ConcreteHandler1 extends Handler {
    public void handleRequest(String request) {
        if (request.equals("one")) {
            System.out.println("具体处理者1负责处理该请求!");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(request);
            } else {
                System.out.println("没有人处理该请求!");
            }
        }
    }
}

//具体处理者角色2
class ConcreteHandler2 extends Handler {
    public void handleRequest(String request) {
        if (request.equals("two")) {
            System.out.println("具体处理者2负责处理该请求!");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(request);
            } else {
                System.out.println("没有人处理该请求!");
            }
        }
    }
}

5,状态模式(State)

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

和常用的请求上下文一样,对象本身视作环境,即上下文,而可变对象是环境内部的一个变量,视作环境的状态。环境对象本身执行时,会根据状态的不同执行不同操作。

public class StatePatternClient {
    public static void main(String[] args) {
        Context context = new Context();    //创建环境
        context.Handle();    //处理请求
        context.Handle();
        context.Handle();
        context.Handle();
    }
}

//环境类
class Context {
    private State state;
    //定义环境类的初始状态
    public Context() {
        this.state = new ConcreteStateA();
    }
    //设置新状态
    public void setState(State state) {
        this.state = state;
    }
    //读取状态
    public State getState() {
        return (state);
    }
    //对请求做处理
    public void Handle() {
        state.Handle(this);
    }
}

//抽象状态类
abstract class State {
    public abstract void Handle(Context context);
}

//具体状态A类
class ConcreteStateA extends State {
    public void Handle(Context context) {
        System.out.println("当前状态是 A.");
        context.setState(new ConcreteStateB());
    }
}

//具体状态B类
class ConcreteStateB extends State {
    public void Handle(Context context) {
        System.out.println("当前状态是 B.");
        context.setState(new ConcreteStateA());
    }
}

6,观察者模式(Observer模式)

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

类似触发模式,给一个对象追加观察者,或者说触发者,当对象本身执行处理或时,通知观察者或者说触发触发者的处理。

public class ObserverPattern {
    public static void main(String[] args) {
        Subject subject = new ConcreteSubject();
        subject.add(new ConcreteObserver1());
        subject.add(new ConcreteObserver2());
        subject.notifyObserver();
    }
}

//抽象目标
abstract class Subject {
    protected List<Observer> observers = new ArrayList<Observer>();
    //增加观察者方法
    public void add(Observer observer) {
        observers.add(observer);
    }
    //删除观察者方法
    public void remove(Observer observer) {
        observers.remove(observer);
    }
    public abstract void notifyObserver(); //通知观察者方法
}

//具体目标
class ConcreteSubject extends Subject {
    public void notifyObserver() {
        System.out.println("具体目标发生改变...");
        System.out.println("--------------");
        for (Object obs : observers) {
            ((Observer) obs).response();
        }

    }
}

//抽象观察者
interface Observer {
    void response(); //反应
}

//具体观察者1
class ConcreteObserver1 implements Observer {
    public void response() {
        System.out.println("具体观察者1作出反应!");
    }
}

//具体观察者1
class ConcreteObserver2 implements Observer {
    public void response() {
        System.out.println("具体观察者2作出反应!");
    }
}

7,中介者模式

定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

观察者模式是对象调用观察者触发,而中介者模式,是中介者对象内的同事类,A和B之间通讯,类似广播的方式。

public class MediatorPattern {
    public static void main(String[] args) {
        Mediator md = new ConcreteMediator();
        Colleague c1, c2;
        c1 = new ConcreteColleague1();
        c2 = new ConcreteColleague2();
        md.register(c1);
        md.register(c2);
        c1.send();
        System.out.println("-------------");
        c2.send();
    }
}

//抽象中介者
abstract class Mediator {
    public abstract void register(Colleague colleague); // 注册
    public abstract void relay(Colleague cl); //转发
}

//具体中介者
class ConcreteMediator extends Mediator {
    private List<Colleague> colleagues = new ArrayList<Colleague>();

    public void register(Colleague colleague) {
        if (!colleagues.contains(colleague)) {
            colleagues.add(colleague);
            colleague.setMedium(this);
        }
    }

    public void relay(Colleague cl) {
        for (Colleague ob : colleagues) {
            if (!ob.equals(cl)) {
                ((Colleague) ob).receive();
            }
        }
    }
}

//抽象同事类
abstract class Colleague {
    protected Mediator mediator;
    public void setMedium(Mediator mediator) {
        this.mediator = mediator;
    }
    public abstract void receive(); // 接受
    public abstract void send(); // 发送
}

//具体同事类
class ConcreteColleague1 extends Colleague {
    public void receive() {
        System.out.println("具体同事类1收到请求。");
    }
    public void send() {
        System.out.println("具体同事类1发出请求。");
        mediator.relay(this); //请中介者转发
    }
}

//具体同事类
class ConcreteColleague2 extends Colleague {
    public void receive() {
        System.out.println("具体同事类2收到请求。");
    }

    public void send() {
        System.out.println("具体同事类2发出请求。");
        mediator.relay(this); //请中介者转发
    }
}

8,迭代器(Iterator)

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

public class IteratorPattern {
    public static void main(String[] args) {
        Aggregate ag = new ConcreteAggregate();
        ag.add("中山大学");
        ag.add("华南理工");
        ag.add("韶关学院");
        System.out.print("聚合的内容有:");
        Iterator it = ag.getIterator();
        while (it.hasNext()) {
            Object ob = it.next();
            System.out.print(ob.toString() + "\t");
        }
        Object ob = it.first();
        System.out.println("\nFirst:" + ob.toString());
    }
}

//抽象聚合
interface Aggregate {
    public void add(Object obj);
    public void remove(Object obj);
    public Iterator getIterator();
}

//具体聚合
class ConcreteAggregate implements Aggregate {
    private List<Object> list = new ArrayList<Object>();
    public void add(Object obj) {
        list.add(obj);
    }
    public void remove(Object obj) {
        list.remove(obj);
    }
    public Iterator getIterator() {
        return (new ConcreteIterator(list));
    }
}

//抽象迭代器
interface Iterator {
    Object first();
    Object next();
    boolean hasNext();
}

//具体迭代器
class ConcreteIterator implements Iterator {
    private List<Object> list = null;
    private int index = -1;

    public ConcreteIterator(List<Object> list) {
        this.list = list;
    }

    public boolean hasNext() {
        if (index < list.size() - 1) {
            return true;
        } else {
            return false;
        }
    }

    public Object first() {
        index = 0;
        Object obj = list.get(index);
        return obj;
    }

    public Object next() {
        Object obj = null;
        if (this.hasNext()) {
            obj = list.get(++index);
        }
        return obj;
    }
}

9,访问者模式(Visitor模式)

将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。

public class VisitorPattern {
    public static void main(String[] args) {
        ObjectStructure os = new ObjectStructure();
        os.add(new ConcreteElementA());
        os.add(new ConcreteElementB());
        Visitor visitor = new ConcreteVisitorA();
        os.accept(visitor);
        System.out.println("------------------------");
        visitor = new ConcreteVisitorB();
        os.accept(visitor);
    }
}

//抽象访问者
interface Visitor {
    void visit(ConcreteElementA element);

    void visit(ConcreteElementB element);
}

//具体访问者A类
class ConcreteVisitorA implements Visitor {
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者A访问-->" + element.operationA());
    }

    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者A访问-->" + element.operationB());
    }
}

//具体访问者B类
class ConcreteVisitorB implements Visitor {
    public void visit(ConcreteElementA element) {
        System.out.println("具体访问者B访问-->" + element.operationA());
    }

    public void visit(ConcreteElementB element) {
        System.out.println("具体访问者B访问-->" + element.operationB());
    }
}

//抽象元素类
interface Element {
    void accept(Visitor visitor);
}

//具体元素A类
class ConcreteElementA implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String operationA() {
        return "具体元素A的操作。";
    }
}

//具体元素B类
class ConcreteElementB implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public String operationB() {
        return "具体元素B的操作。";
    }
}

//对象结构角色
class ObjectStructure {
    private List<Element> list = new ArrayList<Element>();

    public void accept(Visitor visitor) {
        Iterator<Element> i = list.iterator();
        while (i.hasNext()) {
            ((Element) i.next()).accept(visitor);
        }
    }

    public void add(Element element) {
        list.add(element);
    }

    public void remove(Element element) {
        list.remove(element);
    }
}

10,备忘录模式

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。

public class MementoPattern {
    public static void main(String[] args) {
        Originator or = new Originator();
        Caretaker cr = new Caretaker();
        or.setState("S0");
        System.out.println("初始状态:" + or.getState());
        cr.setMemento(or.createMemento()); //保存状态
        or.setState("S1");
        System.out.println("新的状态:" + or.getState());
        or.restoreMemento(cr.getMemento()); //恢复状态
        System.out.println("恢复状态:" + or.getState());
    }
}

//备忘录
class Memento {
    private String state;
    public Memento(String state) {
        this.state = state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
}

//发起人
class Originator {
    private String state;
    public void setState(String state) {
        this.state = state;
    }
    public String getState() {
        return state;
    }
    public Memento createMemento() {
        return new Memento(state);
    }
    public void restoreMemento(Memento m) {
        this.setState(m.getState());
    }
}

//管理者
class Caretaker {
    private Memento memento;
    public void setMemento(Memento m) {
        memento = m;
    }
    public Memento getMemento() {
        return memento;
    }
}

11,解释器模式

给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。

public class InterpreterPatternDemo {
    public static void main(String[] args) {
        Context bus = new Context();
        bus.freeRide("韶关的老人");
        bus.freeRide("韶关的年轻人");
        bus.freeRide("广州的妇女");
        bus.freeRide("广州的儿童");
        bus.freeRide("山东的儿童");
    }
}

//抽象表达式类
interface Expression {
    public boolean interpret(String info);
}

//终结符表达式类
class TerminalExpression implements Expression {
    private Set<String> set = new HashSet<String>();

    public TerminalExpression(String[] data) {
        for (int i = 0; i < data.length; i++) set.add(data[i]);
    }

    public boolean interpret(String info) {
        if (set.contains(info)) {
            return true;
        }
        return false;
    }
}

//非终结符表达式类
class AndExpression implements Expression {
    private Expression city = null;
    private Expression person = null;

    public AndExpression(Expression city, Expression person) {
        this.city = city;
        this.person = person;
    }

    public boolean interpret(String info) {
        String s[] = info.split("的");
        return city.interpret(s[0]) && person.interpret(s[1]);
    }
}

//环境类
class Context {
    private String[] citys = {"韶关", "广州"};
    private String[] persons = {"老人", "妇女", "儿童"};
    private Expression cityPerson;

    public Context() {
        Expression city = new TerminalExpression(citys);
        Expression person = new TerminalExpression(persons);
        cityPerson = new AndExpression(city, person);
    }

    public void freeRide(String info) {
        boolean ok = cityPerson.interpret(info);
        if (ok) System.out.println("您是" + info + ",您本次乘车免费!");
        else System.out.println(info + ",您不是免费人员,本次乘车扣费2元!");
    }
}
posted @ 2020-06-17 16:40  常烦常乐  阅读(143)  评论(0编辑  收藏  举报