23种设计模式详解(以Java为例)

文章目录


创建型 结构型 行为型
工厂模式(简单工厂、工厂方法) 适配器 Adapter 责任链 Chain of Responsibility
抽象工厂模式 桥接 Bridge 命令 Command
原型模式 组合 Composite 解释器 Interpreter
建造者模式 装饰 Decorator 迭代器 Iterator
单例模式 外观 Facade 中介 Mediator
享元 Flyweight 备忘录 Memento
代理 Proxy 观察者 Observer
状态 State
策略 Strategy
模板方法 Template Method
访问者 Visitor
  • 创建型包含5种模式,涉及对象/对象组合的创建构建。
  • 结构性包含7种模式,涉及对象/类之间的关系。
  • 行为型包含11种模式,涉及对象/类的行为、状态、流程。

1、工厂模式

简单工厂

java 复制代码
public class OperationFactory {
    public static Operation createOperation(char operator) {
        Operation operation;

        switch (operator) {
            case '+':
                operation = new OperationAdd();
                break;
            case '-':
                operation = new OperationSub();
                break;
            case '*':
                operation = new OperationMul();
                break;
            case '/':
                operation = new OperationDiv();
                break;
            default:
                throw new RuntimeException("unsupported operation");
        }

        return operation;
    }
}
java 复制代码
public abstract class Operation {
    public double numberA;
    public double numberB;

    public abstract double getResult();
}
java 复制代码
public class OperationAdd extends Operation {

    @Override
    public double getResult() {
        return numberA + numberB;
    }

}
java 复制代码
public class OperationSub extends Operation {

    @Override
    public double getResult() {
        return numberA - numberB;
    }

}
java 复制代码
public class OperationMul extends Operation {

    @Override
    public double getResult() {
        return numberA * numberB;
    }

}
java 复制代码
public class OperationDiv extends Operation {

    @Override
    public double getResult() {
        if (numberB == 0) {
            throw new RuntimeException("divided by 0");
        }
        return numberA / numberB;
    }

}
java 复制代码
/**
 * 使用工厂方法生成实例完成运算操作
 */
public class Calculator {
    public static void main(String[] args) {
        Operation operation;
        char operator;

        operator = '+';
        operation = OperationFactory.createOperation(operator);
        operation.numberA = 1.2;
        operation.numberB = 2.3;

        System.out.println(operation.getResult());
    }
}

工厂方法

工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

java 复制代码
/**
 * 工厂接口
 */
public interface IFactory {
    Operation createOperation();
}
java 复制代码
public class AddFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationAdd();
    }

}
java 复制代码
public class SubFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationSub();
    }

}
java 复制代码
public class MulFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationMul();
    }

}
java 复制代码
public class DivFactory implements IFactory {

    @Override
    public Operation createOperation() {
        return new OperationDiv();
    }

}

类Operation、OperationAdd、OperationSub、OperationMul、OperationDiv同上

java 复制代码
/**
 * 工厂方法客户端
 */
public class FactoryClient {

    public static void main(String[] args) {
        IFactory operFactory = new DivFactory();
        Operation operation = operFactory.createOperation();

        operation.numberA = 3.4;
        operation.numberB = 4.5;

        System.out.println(operation.getResult());

    }
}

2、抽象工厂模式

抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

java 复制代码
// 抽象工厂
public abstract class AbstractFactory {
    public abstract AbstractProductA createProductA();
    public abstract AbstractProductB createProductB();
}
java 复制代码
// 具体工厂1
public class ConcreteFactory1 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB1();
    }
}
java 复制代码
// 具体工厂2
public class ConcreteFactory2 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ProductB2();
    }
}
java 复制代码
// 抽象产品A
public abstract class AbstractProductA {
    public abstract void methodA();
}
java 复制代码
// 具体产品A1
public class ProductA1 extends AbstractProductA {
    @Override
    public void methodA() {
        System.out.println("ProductA1's methodA");
    }
}
java 复制代码
// 具体产品A2
public class ProductA2 extends AbstractProductA {
    @Override
    public void methodA() {
        System.out.println("ProductA2's methodA");
    }
}
java 复制代码
// 抽象产品B
public abstract class AbstractProductB {
    public abstract void methodB();
}
java 复制代码
// 具体产品B1
public class ProductB1 extends AbstractProductB {
    @Override
    public void methodB() {
        System.out.println("ProductB1's methodB");
    }
}
java 复制代码
// 具体产品B2
public class ProductB2 extends AbstractProductB {
    @Override
    public void methodB() {
        System.out.println("ProductB2's methodB");
    }
}
java 复制代码
// 客户端
public class Client {
    public static void main(String[] args) {
        // 使用具体工厂1
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.methodA();
        productB1.methodB();

        // 使用具体工厂2
        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.methodA();
        productB2.methodB();
    }
}

3、原型模式

原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

java 复制代码
// 原型接口
public interface Prototype {
    Prototype clone();
}
java 复制代码
// 具体原型A
public class ConcretePrototypeA implements Prototype {
    @Override
    public Prototype clone() {
        try {
            return (ConcretePrototypeA) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }
}
java 复制代码
// 具体原型B
public class ConcretePrototypeB implements Prototype {
    @Override
    public Prototype clone() {
        try {
            return (ConcretePrototypeB) super.clone();
        } catch (CloneNotSupportedException e) {
            return null;
        }
    }
}
java 复制代码
// 客户端
public class Client {
    public static void main(String[] args) {
        // 创建具体原型A和具体原型B
        ConcretePrototypeA prototypeA = new ConcretePrototypeA();
        ConcretePrototypeB prototypeB = new ConcretePrototypeB();

        // 克隆具体原型A和具体原型B
        ConcretePrototypeA cloneA = (ConcretePrototypeA) prototypeA.clone();
        ConcretePrototypeB cloneB = (ConcretePrototypeB) prototypeB.clone();

        // 检查克隆是否成功
        System.out.println("Clone A == Prototype A: " + (cloneA!= prototypeA));
        System.out.println("Clone B == Prototype B: " + (cloneB!= prototypeB));
    }
}

4、建造者模式

建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

java 复制代码
// 产品类
public class Product {
    private String part1;
    private String part2;

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    public void show() {
        System.out.println("Part 1: " + part1);
        System.out.println("Part 2: " + part2);
    }
}
java 复制代码
// 建造者接口
public interface Builder {
    void buildPart();
    Product getResult();
}
java 复制代码
// 具体建造者类
public class ConcreteBuilder implements Builder {
    private Product product = new Product();

    @Override
    public void buildPart() {
        product.setPart1("Part 1 built by ConcreteBuilder");
        product.setPart2("Part 2 built by ConcreteBuilder");
    }

    @Override
    public Product getResult() {
        return product;
    }
}
java 复制代码
// 指挥者类
public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void construct() {
        builder.buildPart();
    }
}
java 复制代码
// 客户端
public class Client {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);

        director.construct();
        Product product = builder.getResult();
        product.show();
    }
}

5、单例模式

单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。

java 复制代码
/**
 * 线程安全的写法,单例模式最优写法
 */
public class SingletonThreadSafe {
    private static volatile SingletonThreadSafe instance;

    private SingletonThreadSafe() {

    }

    public static SingletonThreadSafe getInstance() {
        if (instance == null) {
            synchronized (SingletonThreadSafe.class) {
                if (instance == null) {
                    instance = new SingletonThreadSafe();
                }
            }
        }

        return instance;
    }
}
java 复制代码
/**
 * 单例模式客户端
 */
public class SingletonClient {
    public static void main(String[] args) {

        SingletonThreadSafe instance1 = SingletonThreadSafe.getInstance();
        SingletonThreadSafe instance2 = SingletonThreadSafe.getInstance();

        if (instance1.equals(instance2)) {
            System.out.println("同样的实例");
        } else {
            System.out.println("不同的实例");
        }

    }
}

6、适配器模式

适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

java 复制代码
/**
 * 需要适配的类
 */
public class Adaptee {

    public void specificRequest() {
        System.out.println("特殊的请求!");
    }

}
java 复制代码
/**
 * 客户所期待的接口
 */
public abstract class Target {
    public void request() {
        System.out.println("普通请求!");
    }
}
java 复制代码
/**
 * 适配器类,通过在内部包装一个Adaptee对象,把原接口转换成目标接口
 */
public class Adapter extends Target {
    private Adaptee adaptee = new Adaptee();

    @Override
    public void request() {
        adaptee.specificRequest();
    }
}
java 复制代码
/**
 * 适配器客户端
 */
public class AdapterClient {

    public static void main(String[] args) {
        Target target = new Adapter();
        target.request();
    }
}

7、桥接模式

桥接模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。

java 复制代码
public abstract class Abstraction {
    /**
     * 桥接模式的关键,使得Abstraction聚合Implementor
     */
    protected Implementor implementor;
    private String name;

    public Abstraction(String name) {
        this.setName(name);
    }

    public void setImplementor(Implementor implementor) {
        this.implementor = implementor;
    }

    public void operation() {
        System.out.print("Abstraction-" + this.getName() + ": ");
        implementor.operation();
    }

    public String getName() {
        return name;
    }

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

class AbstractionA extends Abstraction {

    public AbstractionA(String name) {
        super(name);
    }

    @Override
    public void operation() {
        super.operation();
    }

}

class AbstractionB extends Abstraction {

    public AbstractionB(String name) {
        super(name);
    }

    @Override
    public void operation() {
        super.operation();
    }

}
java 复制代码
public abstract class Implementor {

    public abstract void operation();

}

class ConcreteImplemtorA extends Implementor {

    @Override
    public void operation() {
        System.out.println("ConcreteImplemtorA的方法执行");
    }

}

class ConcreteImplemtorB extends Implementor {

    @Override
    public void operation() {
        System.out.println("ConcreteImplemtorB的方法执行");
    }

}
java 复制代码
/**
 * 客户端
 */
public class BridgeClient {
    public static void main(String[] args) {

        Abstraction a = new AbstractionA("A");
        a.setImplementor(new ConcreteImplemtorA());
        a.operation();
        a.setImplementor(new ConcreteImplemtorB());
        a.operation();

        Abstraction b = new AbstractionB("B");
        b.setImplementor(new ConcreteImplemtorA());
        b.operation();
        b.setImplementor(new ConcreteImplemtorB());
        b.operation();

        // 这样通过使用"组合/聚合复用原则"
        // 如果继续有AbstractionC ... 或者ConcreteImplemtorC ...
        // 只需要扩展类即可,不需要修改现有类,符合"开放-封闭"原则
    }

}

8、组合模式

组合模式,将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

java 复制代码
/**
 * Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。
 */
public abstract class Component {
    protected String name;

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

    public abstract void add(Component component);

    public abstract void remove(Component component);

    public abstract void display(int depth);

    protected String repeatableLayer(int depth) {
        StringBuilder append = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            append.append("-");
        }
        return append.toString();
    }

}
java 复制代码
/**
 * Leaf在组合中表示叶节点对象,叶节点没有子节点
 */
public class Leaf extends Component {

    public Leaf(String name) {
        super(name);
    }

    @Override
    public void add(Component component) {
        System.out.println("cannot add to a leaf");
    }

    @Override
    public void remove(Component component) {
        System.out.println("cannot remove from a leaf");
    }

    @Override
    public void display(int depth) {
        // 通过"-"的数目显示级别
        System.out.println(repeatableLayer(depth) + this.name);
    }

}
java 复制代码
/**
 * 定义有枝节点行为,用来存储子部件
 */
public class Composite extends Component {
    private List<Component> children = new ArrayList<>();

    public Composite(String name) {
        super(name);
    }

    @Override
    public void add(Component component) {
        children.add(component);
    }

    @Override
    public void remove(Component component) {
        children.remove(component);
    }

    @Override
    public void display(int depth) {
        // 显示其枝节点名称,并对其下级进行遍历
        System.out.println(repeatableLayer(depth) + this.name);

        for (Component component : children) {
            component.display(depth + 2);
        }
    }

}
java 复制代码
/**
 * 客户端。通过Component接口操作组合部件的对象
 */
public class CompositeClient {

    public static void main(String[] args) {
        // 生成树根,根上长出两叶Leaf A和Leaf B
        Composite root = new Composite("root");
        root.add(new Leaf("Leaf A"));
        root.add(new Leaf("Leaf B"));

        // 根上长出分支Composite X,分支上也有两叶Leaf X-A和Leaf X-B
        Composite compositeX = new Composite("Composite X");
        compositeX.add(new Leaf("Leaf X-A"));
        compositeX.add(new Leaf("Leaf X-B"));
        root.add(compositeX);

        // 在Composite X上再长出分支Composite X-Y,分支上也有两叶Leaf X-Y-A和Leaf X-Y-B
        Composite compositeXY = new Composite("Composite X-Y");
        compositeXY.add(new Leaf("Leaf X-Y-A"));
        compositeXY.add(new Leaf("Leaf X-Y-B"));
        compositeX.add(compositeXY);

        // 显示大树的样子
        root.display(1);
    }
}

9、装饰模式

装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

java 复制代码
/**
 * Component是定义一个对象接口,可以给这些对象动态地添加职责
 */
public abstract class Component {
    public abstract void operation();
}
java 复制代码
/**
 * ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责
 */
public class ConcreteComponent extends Component {

    @Override
    public void operation() {
        System.out.println("具体对象的操作");
    }

}
java 复制代码
package designpattern.structural.decorator;

/**
 * Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,
 * 是无需知道Decorator的存在的
 */
public abstract class Decorator extends Component {
    protected Component component;

    public Component getComponent() {
        return component;
    }

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }

}

class ConcreteDecoratorA extends Decorator {
    private String addedState;

    @Override
    public void operation() {
        // 首先运行原Component的operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰
        super.operation();
        addedState = "A中的new state ";
        System.out.println(addedState + "具体装饰对象A的操作");
    }
}

class ConcreteDecoratorB extends Decorator {
    @Override
    public void operation() {
        super.operation();
        addedBehavior();
        System.out.println("具体装饰对象B的操作");
    }

    public void addedBehavior() {
        System.out.print("B中的新增行为 ");
    }
}

class ConcreteDecoratorC extends Decorator {
    @Override
    public void operation() {
        super.operation();
        System.out.println("C没有特殊行为 " + "具体装饰对象C的操作");
    }

}

10、外观模式

外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

java 复制代码
/**
 * "系统"接口,只是标记接口,暂无任何意义
 */
public interface SystemInterface {

}

class SubSystemOne implements SystemInterface {
    public void methodOne() {
        System.out.println("子系统方法一");
    }
}

class SubSystemTwo implements SystemInterface {
    public void methodTwo() {
        System.out.println("子系统方法二");
    }
}

class SubSystemThree implements SystemInterface {
    public void methodThree() {
        System.out.println("子系统方法三");
    }
}

class SubSystemFour implements SystemInterface {
    public void methodFour() {
        System.out.println("子系统方法四");
    }
}
java 复制代码
/**
 * 外观类,它需要了解所有的子系统的方法或属性,进行组合,以备外界调用
 */
public class Facade {
    SubSystemOne subSystemOne;
    SubSystemTwo subSystemTwo;
    SubSystemThree subSystemThree;
    SubSystemFour subSystemFour;

    public Facade() {
        subSystemOne = new SubSystemOne();
        subSystemTwo = new SubSystemTwo();
        subSystemThree = new SubSystemThree();
        subSystemFour = new SubSystemFour();
    }

    public void methodA() {
        System.out.println("方法组A:");

        subSystemOne.methodOne();
        subSystemTwo.methodTwo();
        subSystemFour.methodFour();
    }

    public void methodB() {
        System.out.println("方法组B:");

        subSystemThree.methodThree();
        subSystemFour.methodFour();
    }
}
java 复制代码
/**
 * 外观类客户端
 */
public class FacadeClient {
    public static void main(String[] args) {
        // 由于Facade的作用,客户端可以根本不知道四个子系统的存在
        // 启发:维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,此时可以
        // 为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单
        // 的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作
        Facade facade = new Facade();

        facade.methodA();
        facade.methodB();
    }
}

11、享元模式

享元模式,运用共享技术有效地支持大量细粒度的对象。

java 复制代码
/**
 * 享元工厂
 */
public class FlyWeightFactory {
    private HashMap<String, FlyWeight> flyWeights = new HashMap<>();

    public FlyWeight getFlyWeight(String key) {
        if (!flyWeights.containsKey(key)) {
            flyWeights.put(key, new ConcreteFlyWeight());
        }

        return flyWeights.get(key);
    }

}
java 复制代码
/**
 * 所有具体享元类的超类,接受并作用于外部状态
 */
public abstract class FlyWeight {

    public abstract void operation(int extrinsicState);

}

class ConcreteFlyWeight extends FlyWeight {

    @Override
    public void operation(int extrinsicState) {
        System.out.println("具体FlyWeight:" + extrinsicState);
    }

}

class UnsharedConcreteFlyWeight extends FlyWeight {

    @Override
    public void operation(int extrinsicState) {
        System.out.println("不共享的具体FlyWeight:" + extrinsicState);
    }

}
java 复制代码
/**
 * 客户端
 */
public class FlyWeightClient {

    public static void main(String[] args) {
        int extrinsicState = 22;

        FlyWeightFactory factory = new FlyWeightFactory();

        FlyWeight fx = factory.getFlyWeight("X");
        fx.operation(--extrinsicState);

        FlyWeight fy = factory.getFlyWeight("Y");
        fy.operation(--extrinsicState);

        FlyWeight fz = factory.getFlyWeight("Z");
        fz.operation(--extrinsicState);

        FlyWeight uf = new UnsharedConcreteFlyWeight();
        uf.operation(--extrinsicState);
    }

}

12、代理模式

代理模式,为其他对象提供一种代理以控制对这个对象的访问。

java 复制代码
/**
 * 定义真实实体类与代理类共用的接口
 */
public interface Subject {
    void request();
}
java 复制代码
/**
 * 代理类
 */
public class Proxy implements Subject {

    // 保存一个引用,使得代理可以访问真实实体
    Subject subject;

    public Proxy() {
		subject = new RealSubject();
    }

    @Override
    public void request() {
		subject.request();
    }

}
java 复制代码
/**
 * 真实实体类
 */
public class RealSubject implements Subject {

    @Override
    public void request() {
		System.out.println("真实对象的请求");
    }

}

13、解释器模式

解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

java 复制代码
/**
 * 包含解释器之外的一些全局信息
 */
public class Context {

    private String input;
    private String output;

    public String getInput() {
        return input;
    }

    public void setInput(String input) {
        this.input = input;
    }

    public String getOutput() {
        return output;
    }

    public void setOutput(String output) {
        this.output = output;
    }

}
java 复制代码
/**
 * 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
 */
public abstract class AbstractExpression {

    public abstract void interpret(Context context);

}
java 复制代码
/**
 * 实现与文法中的终结符相关联的解释操作,文法中每一个终结符都有一个具体终结表达式与之相对应
 */
public class TerminalExpression extends AbstractExpression {

    @Override
    public void interpret(Context context) {
        System.out.println("终端解释器");
    }

}
java 复制代码
/**
 * 非终结符表达式,为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2 ... ... Rn都需要一个具体的非终结符表达式类。
 */
public class NonTerminalExpression extends AbstractExpression {

    @Override
    public void interpret(Context context) {
        System.out.println("非终端解释器");
    }

}
java 复制代码
/**
 * 构建表示该文法定义的语言中一个特定的句子的抽象语法树,调用解释操作
 */
public class InterpreterClient {

    public static void main(String[] args) {
        Context context = new Context();
        List<AbstractExpression> list = new ArrayList<>();

        list.add(new TerminalExpression());
        list.add(new NonTerminalExpression());
        list.add(new TerminalExpression());
        list.add(new TerminalExpression());

        for (AbstractExpression expression : list) {
            expression.interpret(context);
        }
    }

}

14、模板方法模式

模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

java 复制代码
/**
 * 模板方法抽象类:不变的部分给出具体实现,变化的部分封装为抽象方法延迟到子类实现
 */
public abstract class AbstractTemplate {
    public abstract void primitiveOperation1();
    public abstract void primitiveOperation2();

    public void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
        System.out.println("模板方法结束\n");
    }
}
java 复制代码
/**
 * 具体类A
 */
public class ConcreteClassA extends AbstractTemplate {

    @Override
    public void primitiveOperation1() {
        System.out.println("具体类A的方法1实现");
    }

    @Override
    public void primitiveOperation2() {
        System.out.println("具体类A的方法2实现");
    }
}
java 复制代码
/**
 * 具体类B
 */
public class ConcreteClassB extends AbstractTemplate {

    @Override
    public void primitiveOperation1() {
        System.out.println("具体类B的方法1实现");
    }

    @Override
    public void primitiveOperation2() {
        System.out.println("具体类B的方法2实现");
    }
}
java 复制代码
/**
 * 模板方法客户端
 */
public class TemplateClient {
    public static void main(String[] args) {
        AbstractTemplate abstractTemplate;

        abstractTemplate = new ConcreteClassA();
        abstractTemplate.templateMethod();

        abstractTemplate = new ConcreteClassB();
        abstractTemplate.templateMethod();
    }
}

15、策略模式

场景:商场促销。简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂。所以它不是最好的办法。

面对算法的时常变动,应该有更好的办法。

策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

java 复制代码
/**
 * 上下文
 */
public class Context {

    Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    /**
     * 上下文接口
     */
    public void contextInterface() {
        strategy.algorithmInterface();
    }
}
java 复制代码
/**
 * 策略接口
 */
public interface Strategy {
    void algorithmInterface();
}

class ConcreteStrategyA implements Strategy {

    @Override
    public void algorithmInterface() {
        System.out.println("策略A的具体算法实现");
    }
}

class ConcreteStrategyB implements Strategy {

    @Override
    public void algorithmInterface() {
        System.out.println("策略B的具体算法实现");
    }
}

class ConcreteStrategyC implements Strategy {

    @Override
    public void algorithmInterface() {
        System.out.println("策略C的具体算法实现");
    }
}
java 复制代码
package designpattern.behavioral.strategy;

/**
 * 客户端使用策略
 */
public class StrategyClient {

    public static void main(String[] args) {
        Context context;

        context = new Context(new ConcreteStrategyA());
        context.contextInterface();

        context = new Context(new ConcreteStrategyB());
        context.contextInterface();

        context = new Context(new ConcreteStrategyC());
        context.contextInterface();
    }
}

16、观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

java 复制代码
/**
 * 主题或抽象通知者
 */
public abstract class Subject {
    private List<Observer> observers = new ArrayList<>();

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

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

    public void notifyObserver() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
java 复制代码
/**
 * 具体主题或通知者
 */
public class ConcreteSubject extends Subject {
    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }
}
java 复制代码
/**
 * 抽象观察者
 */
public abstract class Observer {
    public abstract void update();
}
java 复制代码
/**
 * 具体观察者
 */
public class ConcreteObserver extends Observer {

    private String name;
    private String observerState;
    private ConcreteSubject concreteSubject;

    public ConcreteObserver(ConcreteSubject concreteSubject, String name) {
        this.setName(name);
        this.setConcreteSubject(concreteSubject);
    }

    @Override
    public void update() {
        this.setObserverState(concreteSubject.getSubjectState());
        System.out.println("观察者" + this.getName() + "的新状态是" + this.getObserverState());
    }

    public String getName() {
        return name;
    }

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

    public String getObserverState() {
        return observerState;
    }

    public void setObserverState(String observerState) {
        this.observerState = observerState;
    }

    public ConcreteSubject getConcreteSubject() {
        return concreteSubject;
    }

    public void setConcreteSubject(ConcreteSubject concreteSubject) {
        this.concreteSubject = concreteSubject;
    }
}
java 复制代码
/**
 * 观察者模式客户端代码
 */
public class ObserverClient {
    public static void main(String[] args) {
        ConcreteSubject concreteSubject = new ConcreteSubject();

        concreteSubject.attach(new ConcreteObserver(concreteSubject, "X"));
        concreteSubject.attach(new ConcreteObserver(concreteSubject, "Y"));
        concreteSubject.attach(new ConcreteObserver(concreteSubject, "Z"));

        concreteSubject.setSubjectState("ABC");
        concreteSubject.notifyObserver();
    }
}

17、状态模式

状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

java 复制代码
/**
 * Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
 */
public class Context {
    private State state;

    public Context(State state) {
        this.state = state;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        this.state.handle(this);
    }
}
java 复制代码
/**
 * 抽象状态类
 */
public abstract class State {
    public abstract void handle(Context context);
}

class ConcreteStateA extends State {

    @Override
    public void handle(Context context) {
        System.out.println("现在是在状态A");
        context.setState(new ConcreteStateB());
    }
}

class ConcreteStateB extends State {

    @Override
    public void handle(Context context) {
        System.out.println("现在是在状态B");
        context.setState(new ConcreteStateC());
    }
}

class ConcreteStateC extends State {

    @Override
    public void handle(Context context) {
        System.out.println("现在是在状态C");
        context.setState(new ConcreteStateA());
    }
}
java 复制代码
/**
 * 客户端:不断请求,不断更改状态
 */
public class StateClient {
    public static void main(String[] args) {

        Context context = new Context(new ConcreteStateA());

        context.request();
        context.request();
        context.request();
        context.request();
        context.request();
    }
}

18、备忘录模式

备忘录:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

java 复制代码
/**
 * 发起人(Originator) 类
 */
public class Originator {

    private String state;

    public Memento createMemento() {
        return new Memento(this.state);
    }

    public void recoverMemento(Memento memento) {
        this.setState(memento.getState());
    }

    public void show() {
        System.out.println("state = " + this.state);
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}
java 复制代码
/**
 * 备忘录(Memento)类
 */
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}
java 复制代码
/**
 * 管理者(CareTaker)类:管理备忘录
 */
public class CareTaker {

    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}
java 复制代码
/**
 * 客户端
 */
public class MementoClient {

    public static void main(String[] args) {
        // 设置初始状态
        Originator originator = new Originator();
        originator.setState("On");
        originator.show();

        // 管理者通过备忘录保存状态,由于有了很好地封装,可以隐藏Originator的实现细节
        CareTaker careTaker = new CareTaker();
        careTaker.setMemento(originator.createMemento());

        // 改变状态
        originator.setState("Off");
        originator.show();

        // 通过管理者从备忘录中恢复状态
        originator.recoverMemento(careTaker.getMemento());
        originator.show();
    }
}

19、迭代器模式

迭代器模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

java 复制代码
/**
 * 聚集接口
 *
 * @param <T>
 */
public interface Aggregate<T> {

    Iterator<T> createIterator();
}
java 复制代码
/**
 * 具体聚集类
 *
 * @param <T>
 */
public class ConcreteAggregate<T> implements Aggregate<T> {

    private List<T> items = new ArrayList<>();

    @Override
    public Iterator<T> createIterator() {
        return new ConcreteIterator<T>(this);
    }

    public int count() {
        return items.size();
    }

    public T getItems(int index) {
        return items.get(index);
    }

    public void setItems(T item) {
        items.add(item);
    }
}
java 复制代码
/**
 * 迭代器接口
 *
 * @param <T>
 */
public interface Iterator<T> {

    T first();

    T next();

    boolean isDone();

    T currentItem();
}
java 复制代码
/**
 * 具体迭代器类,给出一种具体迭代的实现方式。思考:迭代器表示的是一种迭代的行为,而聚集则是真正要被迭代的数据集合。
 * 之所以要将迭代器和聚集分开,就是为了将行为与数据分开。 可类比Java中Iterator与Iterable的关系进行理解
 *
 * @param <T>
 */
public class ConcreteIterator<T> implements Iterator<T> {

    private ConcreteAggregate<T> concreteAggregate;
    private int current = 0;

    public ConcreteIterator(ConcreteAggregate<T> concreteAggregate) {
        this.setConcreteAggregate(concreteAggregate);
    }

    @Override
    public T first() {
        return concreteAggregate.getItems(0);
    }

    @Override
    public T next() {
        current++;

        if (current < concreteAggregate.count()) {
            return concreteAggregate.getItems(current);
        }

        return null;
    }

    @Override
    public boolean isDone() {
        return current >= concreteAggregate.count() ? true : false;
    }

    @Override
    public T currentItem() {
        return concreteAggregate.getItems(current);
    }

    public ConcreteAggregate<T> getConcreteAggregate() {
        return concreteAggregate;
    }

    public void setConcreteAggregate(ConcreteAggregate<T> concreteAggregate) {
        this.concreteAggregate = concreteAggregate;
    }

    public int getCurrent() {
        return current;
    }

    public void setCurrent(int current) {
        this.current = current;
    }
}
java 复制代码
/**
 * 迭代器客户端
 */
public class IteratorClient {
    public static void main(String[] args) {
        ConcreteAggregate<String> bus = new ConcreteAggregate<String>();

        bus.setItems("大鸟");
        bus.setItems("小菜");
        bus.setItems("行李");
        bus.setItems("老外");
        bus.setItems("公交内部员工");
        bus.setItems("小偷");

        Iterator<String> iterator = new ConcreteIterator<>(bus);

        while (!iterator.isDone()) {
            System.out.println(iterator.currentItem() + "请买票!");
            iterator.next();
        }
    }
}

20、命令模式

命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以 及支持可撤销的操作。

java 复制代码
/**
 * 用来声明执行操作的接口
 */
public abstract class Command {

    protected List<Reciever> recievers;

    public Command(List<Reciever> recievers) {
        this.recievers = recievers;
    }

    public void addRecievers(Reciever reciever) {
        this.recievers.add(reciever);
    }

    public abstract void execute();

}

// 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现execute
class ConcreteCommand extends Command {

    public ConcreteCommand(List<Reciever> recievers) {
        super(recievers);
    }

    @Override
    public void execute() {
        for (Reciever reciever : recievers) {
            reciever.action();
        }
    }
}
java 复制代码
/**
 * 知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。真正执行请求的地方!
 */
interface Reciever {
    void action();
}

class RecieverA implements Reciever {

    @Override
    public void action() {
        System.out.println("RecieverA执行请求!");
    }

}

class RecieverB implements Reciever {

    @Override
    public void action() {
        System.out.println("RecieverB执行请求!");
    }
}

class RecieverC implements Reciever {

    @Override
    public void action() {
        System.out.println("RecieverC执行请求!");
    }
}
java 复制代码
/**
 * 要求该命令执行这个请求
 */
public class Invoker {

    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void executeCommand() {
        command.execute();
    }
}
java 复制代码
/**
 * 创建一个具体命令对象并设定它的接收者
 */
public class CommandClient {

    public static void main(String[] args) {
        List<Reciever> recievers = new ArrayList<>();

        recievers.add(new RecieverA());
        recievers.add(new RecieverB());
        recievers.add(new RecieverC());

        Command command = new ConcreteCommand(recievers);
        Invoker invoker = new Invoker();

        invoker.setCommand(command);
        invoker.executeCommand();
    }
}

21、责任链模式

责任链模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

java 复制代码
/**
 * 处理请求的接口
 */
public abstract class Handler {

    protected Handler successor;

    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

    public abstract void handleRequest(int request);
}

/**
 * 具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,则处理,否则转给它的后继者处理
 */
class ConcreteHandlerA extends Handler {

    @Override
    public void handleRequest(int request) {
        if (request >= 0 && request <= 10) {
            System.out.println(this.getClass().getName() + "处理了请求" + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }

}

class ConcreteHandlerB extends Handler {

    @Override
    public void handleRequest(int request) {
        if (request > 10 && request <= 20) {
            System.out.println(this.getClass().getName() + "处理了请求" + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }

}

class ConcreteHandlerC extends Handler {

    @Override
    public void handleRequest(int request) {
        if (request > 20 && request <= 30) {
            System.out.println(this.getClass().getName() + "处理了请求" + request);
        } else if (successor != null) {
            successor.handleRequest(request);
        }
    }
}
java 复制代码
/**
 * 向链上的具体处理者对象提交请求
 */
public class Client {
    public static void main(String[] args) {

        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        Handler handlerC = new ConcreteHandlerC();

        handlerA.setSuccessor(handlerB);
        handlerB.setSuccessor(handlerC);

        int[] requests = {2, 14, 5, 6, 8, 23, 12, 21};

        for (int i : requests) {
            handlerA.handleRequest(i);
        }
    }
}

22、中介者模式

中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

java 复制代码
/**
 * 抽象同事类
 */
public abstract class Colleague {

    protected Mediator mediator;

    public Colleague(Mediator mediator) {
        this.mediator = mediator;
    }

    public abstract void sendMsg(String message);

    public abstract void notifyMsg(String message);

}

class ConcreteColleague1 extends Colleague {

    public ConcreteColleague1(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void sendMsg(String message) {
        mediator.send(message, this);
    }

    @Override
    public void notifyMsg(String message) {
        System.out.println("同事1得到消息:" + message);
    }

}

class ConcreteColleague2 extends Colleague {

    public ConcreteColleague2(Mediator mediator) {
        super(mediator);
    }

    @Override
    public void sendMsg(String message) {
        mediator.send(message, this);
    }

    @Override
    public void notifyMsg(String message) {
        System.out.println("同事2得到消息:" + message);
    }
}
java 复制代码
/**
 * 抽象中介者类
 */
public abstract class Mediator {

    public abstract void send(String message, Colleague colleague);

}

class ConcreteMediator extends Mediator {
    // 需要了解所有的具体同事对象
    private ConcreteColleague1 c1;
    private ConcreteColleague2 c2;

    public ConcreteColleague1 getC1() {
        return c1;
    }

    public void setC1(ConcreteColleague1 c1) {
        this.c1 = c1;
    }

    public ConcreteColleague2 getC2() {
        return c2;
    }

    public void setC2(ConcreteColleague2 c2) {
        this.c2 = c2;
    }

    @Override
    public void send(String message, Colleague colleague) {
        // 重写发送信息的方法,根据对象做出选择判断,通知对象
        if (colleague == c1) {
            c2.notifyMsg(message);
        } else {
            c1.notifyMsg(message);
        }
    }
}
java 复制代码
/**
 * 客户端
 */
public class MediatorClient {

    public static void main(String[] args) {
        ConcreteMediator concreteMediator = new ConcreteMediator();

        // 让两个具体同事类认识中介者对象
        ConcreteColleague1 concreteColleague1 = new ConcreteColleague1(concreteMediator);
        ConcreteColleague2 concreteColleague2 = new ConcreteColleague2(concreteMediator);

        // 让中介者认识各个具体同事类对象
        concreteMediator.setC1(concreteColleague1);
        concreteMediator.setC2(concreteColleague2);

        // 具体同事类对象的消息发送都是通过中介者对象转发
        concreteColleague1.sendMsg("吃过饭了没有?");
        concreteColleague2.sendMsg("没有呢,你打算请客?");
    }
}

23、访问者模式

访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

java 复制代码
/**
 * 为该对象结构中ConcreteElement的每一个类声明一个Visit操作
 */
public abstract class Visitor {

    public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);

    public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);

}

class ConcreteVisitor1 extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
		System.out.println(concreteElementA.getClass().getSimpleName() + "被"
			+ this.getClass().getSimpleName() + "访问");
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
		System.out.println(concreteElementB.getClass().getSimpleName() + "被"
			+ this.getClass().getSimpleName() + "访问");
    }
}

class ConcreteVisitor2 extends Visitor {

    @Override
    public void visitConcreteElementA(ConcreteElementA concreteElementA) {
		System.out.println(concreteElementA.getClass().getSimpleName() + "被"
			+ this.getClass().getSimpleName() + "访问");
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB concreteElementB) {
		System.out.println(concreteElementB.getClass().getSimpleName() + "被"
			+ this.getClass().getSimpleName() + "访问");
    }
}
java 复制代码
/**
 * 定义一个accept操作,它以一个访问者为参数
 */
public abstract class Element {
    public abstract void accept(Visitor visitor);
}

class ConcreteElementA extends Element {

    @Override
    public void accept(Visitor visitor) {
		visitor.visitConcreteElementA(this);
    }
}

class ConcreteElementB extends Element {

    @Override
    public void accept(Visitor visitor) {
		visitor.visitConcreteElementB(this);
    }
}
java 复制代码
/**
 * 提供一个高层的接口以允许访问者访问它的元素
 */
public class ObjectStructure {

    private List<Element> elements = new ArrayList<>();

    public void attach(Element element) {
        elements.add(element);
    }

    public void detach(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}
java 复制代码
/**
 * 客户端
 */
public class VisitorClient {

    public static void main(String[] args) {
        ObjectStructure o = new ObjectStructure();

        o.attach(new ConcreteElementA());
        o.attach(new ConcreteElementB());

        ConcreteVisitor1 visitor1 = new ConcreteVisitor1();
        ConcreteVisitor2 visitor2 = new ConcreteVisitor2();

        o.accept(visitor1);
        o.accept(visitor2);
    }
}

提示:更多内容可以访问Clang's Blog:https://www.clang.asia

相关推荐
苹果醋317 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
晓纪同学34 分钟前
QT-简单视觉框架代码
开发语言·qt
威桑34 分钟前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
Hello.Reader37 分钟前
深入解析 Apache APISIX
java·apache
飞飞-躺着更舒服37 分钟前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生43 分钟前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生1 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans1 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭1 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel