常用设计模式介绍

前言

简说设计模式。

一、设计模式的要素

1、设计模式解决的问题

  • 某个问题经常发生,这个模式就描述了这个问题以及解决这个问题的解决方法的核心

2、设计模式分类

1)创建型设计模式
  • 与对象的创建有关;
2)结构型设计模式
  • 处理类或对象的组合;
3)行为型设计模式
  • 对类或对象怎样交互和怎么分配职责进行描述;

二、详细介绍

1、创建型设计模式

1)工厂方法模式
a、适用范围
  • 定义一个用于创建对象的接口,让子类决定实例化哪个类
b、代码示例
public class SimpleFactory {
    public static void main(String[] args) {
        // 工厂A创造A产品,工厂B创造B产品
        // 父类 对象名 = new 子类()
        Factory factoryA = new FactoryA();
        Product productA = factoryA.createProduct();
        productA.info();
        
        Factory factoryB = new Factory();
        Product productB = factoryB.createProduct();
        productB.info();
    }
}

interface Product {
    public void info();
}

class ProductA implements Product {
    
    @Override
    public void info() {
        System.out.println("产品的信息:A");
    }
}

class ProductB implements Product {
    
    @Override
    public void info() {
        System.out.println("产品的信息:B");
    }
}

interface Factory {
    public Product createProduct();
}

class FactoryA implements Factory {
    
    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

class FactoryB implements Factory {
    
    @Override
    public PProduct createProduct() {
        return new ProductB();
    }
}
2)抽象工厂模式
a、适用范围
  • 提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类;
  • 如何区分抽象工厂模式还是工厂方法模式?
    • 看具体的一个工厂可以创建多少个类的产品
      • 可以创建多个类的产品的话是抽象工厂模式;
      • 如果只能创建一个类的产品那么是工厂方法模式;
b、代码示例
public class AbstractFactory {
    public static void main(String[] args) {
        Factory factory1 = new Factory1();
        ProductA productA =  factory1.createProductA();
        ProductA productB =  factory1.createProductB();
        productA.info();
        
        Factory factory2 = new Factory1();
        ProductA productA =  factory2.createProductA();
        ProductB productB =  factory2.createProductB();
        productB.info();
    }
}

interface ProductA {
    public void info();
}

class ProductA1 implements ProductA {
    
    @Override
    public void info() {
        System.out.println("产品的信息:A1");
    }
}

class ProductA2 implements ProductA {
    
    @Override
    public void info() {
        System.out.println("产品的信息:A2");
    }
}

interface ProductB {
    public void info();
}

class ProductB1 implements ProductB {
    
    @Override
    public void info() {
        System.out.println("产品的信息:B1");
    }
}

class ProductB2 implements ProductB {
    
    @Override
    public void info() {
        System.out.println("产品的信息:B2");
    }
}

interface Factory {
    public ProductA createProductA();
    public ProductB createProductB();
}

class Factory1 implements Factory {
    
    @Override
    public ProductA createProductA() {
        return new ProductA1();
    }
    
    @Override
    public ProductB createProductB() {
        return new ProductB1();
    }
}

class Factory2 implements Factory {
    
    @Override
    public ProductA createProductA() {
        return new ProductA2();
    }
    
    @Override
    public ProductB createProductB() {
        return new ProductB2();
    }
}
3)生成器模式
a、适用范围
  • 生成器主要负责创建产品的每个部件;
  • 根据具体的生成器创建具体的对象;
  • 将一个复杂对象的创建与它的表示分离,使得同样的创建过程可以创建不同的表示;
b、代码示例
// 生成导演
// 导演调用生成器生成零件的方法
// 同样的构建过程可以创建不同的表示
// 导演 去使用具体的生成器,生成器来创建对应的产品,再将产品给返回(通过 getResult() )给导演

public class Main {
    public static void main(String[] args) {
        Directory director = new Directory();  // 生成导演
        
        Builder builder1 = new Builder1();
        director.Construct(builder1);  // 导演调用不同的生成器,生成器创建对应的产品
        Product product1 = builder1.getResult();  // 将产品返回
        product1.show();
        
        Builder builder2 = new Builder2();
        director.Construct(builder2);
        Product product2 = builder2.getResult();
        product2.show();
    }
}

class Directory {  // 导演用于生成 生成器
    
    public void Construct(Builder builder) {
        builder.BuildPart();  // 生成产品
    }
}


class Product {  // 产品
    // 产品的组成
    List<String> parts = new ArrayList<>();
    
    public void Add(String part) {
        parts.add(part);
    }
    
    public void Show() {
        System.out.println("产品的组成:");
        for (String str : parts)
            System.out.println(s + " ");
    }
}

abstract class Builder {  // 生成器
    public abstract void BuildPart();
    public abstract Product getResult();
}

class Builder1 extends Builder {  // 生成器1
    Product product = new Product();
    
    @Override
    public void BuildPart() {
        product.Add("A");
        product.Add("B");
        product.Add("C");
        product.Add("D");
    }
    
    @Override
    public Product getResult() {
        return product;
    }
}

class Builder2 extends Builder {  // 生成器2
    Product product = new Product();
    
    @Override
    public void BuildPart() {
        product.Add("A");
        product.Add("B");
    }
    
    @Override
    public Product getResult() {
        return product;
    }
}
4)原型模式
a、适用范围
  • 用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象;
b、代码示例
public class Main {
    public static void main(String[] args) {
        Product product1 = new Product(2022, 5.28);
        System.out.println(product1.getId() + " " + product1.getPrice());  // 输出为2022,5.28
        
        Product product2 = (Product) product1.clone();
        System.out.println(product2.getId() + " " + product2.getPrice());  // 输出为2022,5.28
        
        Product product3 = (Product) product1.clone();
        System.out.println(product3.getId() + " " + product3.getPrice());  // 输出为2022,5.28
    }
}

interface Prototype {
    public Object clone();
}

class Product implements Prototype {
    private int id;
    private double price;
    
    public Product() {}
    
    public Product() {
        this.id = id;
        this.price = price;
    }
    
    public int getId() {
        return id;
    }
    
    public double getPrice() {
        return price;
    }
    
    @Override
    public Object Clone() {
        Product object = new Product();
        object.id = this.id;
        object.price = this.price;
        
        return object;
    }
}
5)单例模式
a、适用范围
  • 保证一个类仅有一个实例,并提供一个访问它的全局访问点;
b、代码示例
public class SinglePattern {
    public static void main(String[] args) {
        // 三个是同一个对象
        Singleton singleon1 = Singleton.getInstance();
        Singleton singleon2 = Singleton.getInstance();
        Singleton singleon3 = Singleton.getInstance();
    }
}

class Singleton {
    private int number = 2022;
    
    public void setNumber(int number) {
        this.number = number;
    }
    
    public int getNumber() {
        return number;
    }
    
    private Singleton() {};
    
    private static Singleton instance = new Singleton();  // 对象是属于类的,是唯一的
    
    public static Singleton getInstance() {
        return instance;
    }
}

2、结构型设计模式

1)适配器模式
a、适用范围
  • 将一个类的接口转换成客户希望的另外一个接口
b、代码示例
public class AdapterPattern {
    public static void main(String[] args) {
        USB usb = new Adapter();
        usb.Request();
    }
}

class USB {  
    public void Request() {
        System.out.println("USB数据线");
    }
}

class Adapter extends USB {
    private TypeC typeC = new TypeC();
    
    @Override
    public void Request() {
        typeC.SpecificRequest();
    }
}

class TypeC {
    public void SpecificRequest() {
        System.out.println("TypeC数据线");
    }
}
2)桥接模式
a、适用范围
  • 将抽象部分与其实现部分分离,使它们都可以独立地变化;
b、代码示例
public class BridgePattern {
    public static void main(String[] args) {
        Product productA1 = new ProductA();
        Product productA2 = new ProductA();
        Color red = new Color();
        Color blue = new Color();
        
        productA1.setName("产品A1");
        productA1.setColor(red);
        productA1.Operation();
        
        productA1.setName("产品A2");
        productA1.setColor(blue);
        productA1.Operation();
    }
}

abstract class Product {
    private String name;
    protected Color color;
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void setColor(String color) {
        this.color = color;
    }
    
    public String getColor() {
        return color;
    }
    
    void abstract void Operation();
}

class ProductA extends Product {
    
    @Override
    public void Operation() {
        color.OperationImp();
    }
}

interface Color {
    public void OperationImp(String name);
}

class Red implements Color {
    
    @Override
    public void OperationImp(String name) {
        System.out.println(name + ":红色");
    }
}

class Blue implements Color {
    
    @Override
    public void OperationImp(String name) {
        System.out.println(name + ":蓝色");
    }
}
3)组合模式
a、适用范围
  • 将对象组合成树型结构以表示 “部分 - 整体” 的层次结构
b、代码示例
public class CompositePattern {
    public static void main(String[] args) {
        AbstractFile root = new Folder("root");  // 根目录
        
        AbstractFile folderA = new Folder("folderA");
        folderA.printName();
        
        AbstractFile fileB = new File("fileB");
        fileB.printName();
        
        root.Add(folderA);
        root.Add(fileB);
        
        root.Remove(fileB);
        print(root);
    }
    
    // 获取传入文件夹对应下一层孩子的集合
    static void print(AbstractFile file) {
        file.printName();  // 打印根节点
        
        List<AbstractFile> childrenList = file.getChildren();  // 获取根节点下一层的节点
        if (childrenList == null) return;
        for (AbstractFile children : childrenList) {  // 遍历输出打印
            children.printName();  // 只打印根几点下一层的
            print(children);  // 继续遍历打印下面层的文件和文件夹
        }
    }
} 


abstract class AbstractFile {
    protected String name;
    
    public void printName() {
        System.out.println(name);
    }
    
    public abstract boolean Add(AbstractFile file);
    public abstract boolean Remove(AbstractFile file);
    public abstract List<AbstractFile> getChildren();
}

class Folder extends AbstractFile {
    private List<AbstractFile> childrenList = new ArrayList<>();
    
    public Folder(String name) {
        this.name = name;
    }
    
    @Override
    public void Add(AbstractFile file) {
        return childrenList.add(file);
    }
    
    @Override
    public void Remove(AbstractFile file) {
        return childrenList.remove(file);
    }
    
    @Override
    public List<AbstractFile> getChildren() {  // 文件夹存储子组件(文件夹/文件)
        return childrenList;
    }
}

class File extends AbstractFile {
    
    public File(String name) {
        this.name = name;
    }
    
    @Override
    public void Add(AbstractFile file) {
        return false;
    }
    
    @Override
    public void Remove(AbstractFile file) {
        return false;
    }
    
    @Override
    public List<AbstractFile> getChildren() {
        return false;  // 文件中不能存储子文件和子文件夹
    }
}
4)装饰器模式
a、适用范围
  • 装饰器可以理解为添加一个额外的操作;
  • 动态地给一个对象添加一些额外的职责;
b、代码示例
public class DecoratorPattern {
    
    public static void main(String[] args) {
        // 第一种写法
        // 父类名 对象名 = new 子类名()
        Person zhangsan = new Student("张三");
        // 给张三添加额外的职责
        // 父类名 对象名 = new 子类名()
        // Decorator decoratorA =  new DecoratorA(zhangsan);
        // Person decoratorA =  new DecoratorA(zhangsan);  // 任意一个父类的名都可以赋值上去
        zhangsan = new DecoratorA(zhangsan);  // 直接让张三来接收新增的职责(将添加了新职责的张三再赋值给张三)
        zhangsan = new DecoratorB(zhangsan);
        zhangsan.Operation();  
        
        
        // 第二种写法:采用对象链
        Person lisi = new DecoratorB(new DecoratorA(new Student("李四"));
        lisi.Operation();
    }
    
}

abstract class Person {
    protected String name;
    public abstract void Operation();// 职责
}

abstract class Decorator extends Person {
    protected Person person;
}

// 在实例化装饰器A的时候,将Person对象确定下来
class DecoratorA extends Decorator {
    public DecoratorA(Person person) {
        this.person = person;
    }
    
    @Override
    public void Operation() {  // 职责
        person.Operation();  // 原本的职责(调用当前对象的Operation方法)
        System.out.println("写作业");  // 新添加的职责
    }
}

class DecoratorB extends Decorator {
    public DecoratorA(Person person) {
        this.person = person;
    }
    
    @Override
    public void Operation() {  // 职责
        person.Operation();  // 原本的职责(调用当前对象的Operation方法)
        System.out.println("考试");  // 新添加的职责
    }
}


class Student extends Person {
    public Student(String name) {
        this.name = name;
    }
    
    @Override
    public void Operation() {
        System.out.println(name + "的职责:学习");
    }
}
5)享元模式
a、适用范围
  • 细粒度:对业务模型中的对象进行细分得到更加科学合理的对象(将对象进行细分,得到更多的对象);
  • 享元模式的目的:就是为了减少创建对象的数量,减轻计算机的存储开销;
6)代理模式
a、适用范围
  • 为其它对象提供一种代理以控制对这个对象的访问;
  • 不用自己买,让代理买,代理只需要调用自己的付钱的方法即可;
b、代码示例
public class ProxyPattern {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Proxy proxy = new Proxy(realSubject);
        
        proxy.buy();
    }
}

interface Subject {
    public void buy();
}

class RealSubject implements Subject {
    @Override
    public void buy() {
        System.out.println("付钱");
    }
}

class Proxy implements Subject {  // 代理
    protected RealSubject realSubject;
    
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
    
    @Override
    public void buy() {
        System.out.println("办理购买前的手续");
        realSubject.buy();  // 让购买者付钱
        System.out.println("办理购买后的手续");
    }
}s
7)外观模式

3、行为型设计模式

1)观察者模式
a、适用范围
  • 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新;
b、代码示例
public class ObserverPattern {
    public static void main(String[] args) {
        Subject subjectA = new ConcreteSubject("目标A");  // 一个主题
        // 可以定义多个目标
        
        // 将主题A添加到三个观察者列表中
        Observer observerB = new ConcreteObserver("张三", subjectA);  // 让张三去观察主题A
        Observer observerC = new ConcreteObserver("李四", subjectA);  // 让李四去观察主题A
        Observer observerD = new ConcreteObserver("王五", subjectA);  // 让王五去观察主题A
        
        subjectA.setState("更新了");
        // subjectA.Notify();
    }
}

interface Subject {
    public void Attach(Observer observer);  // 添加观察者
    public void Detach(Observer observer);  // 删除观察者
    public void Notify();  // 状态改变后 通知所有观察者更新状态
    
    public void setState(String state);  // 设置状态
    public String getState();  // 获取状态
}

class ConcreteSubject implements Subject {
    private String name;
    private List<Observer> observerlist;
    private String state;
    
    public ConcreteSubject(String name) {  // 在构造函数中进行初始化
        this.name = name;
        observerlist = new ArrayList<>();
        state = "未更新";
    }
    
    public void setState(String state) {
        this.state = state;
        
        Notify();  // 修改之后并更新状态使所有观察者的状态和修改后的状态保持一致
    }
    
    public String getState() {
        return state;
    }
    
    public void Attach(Observer observer) {
        observerlist.add(observer);
    }
    
    public void Detach(Observer observer) {
        observerlist.remove(observer);
    }
    
    public void Notify() {
        // 更新所有观察者的状态
        for (Observer observer : observerlist) {
            observer.update();
        }
    }
}

interface Observer {  // 观察者接口
    public void update();  // 收到通知,更新观察者的状态
}

class ConcreteObserver implements Observer {
    private String name;
    private String state;  // 保持观察者的状态与目标状态一致
    private Subject subject;
    
    public ConcreteObserver(String name, Subject subject) {
        this.name = name;
        
        this.subject = subject;
        subject.Attach(this);  // 将当前观察者添加到目标中
        
        state = subject.getState();  // 让当前观察者的状态与目标状态保持一致
    }
    
    @Override
    public void update() {
        System.out.println(name + "收到通知");
        state = subject.getState();  // 让当前观察者的状态和修改后的状态之后的目标的状态保持一致
    }
    
}
2)状态模式
a、适用范围
  • 允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎改变了它的类;
b、代码示例
public class StatePattern {
    
    public static void main(String[] args) {
        Context context = new Context();  // 实例化一个贩卖机
        
        System.out.println(context.getState()); 
        
        context.Request();  // 购买一个饮料 count = 2
        context.Request();  // 购买一个饮料 count = 1
        context.Request();  // 购买一个饮料 count = 0
        
        System.out.println(context.getState()); 
        
        context.Request();  // 库存为0,进行补货
    }
}

class Context {  // 贩卖机
    private int count;  // 库存
    private State state;  // 状态
    
    public Context() {
        count = 3;
        state = new StateA();  // 初始库存不为0(状态A)
    }
    
    public void setCount(int count) {
        this.count = count;
    }
    
    public int getCount() {
        return count;
    }
    
    public void setState(State state) {
        this.state = state;
    }
    
    public State getState() {
        return state;
    }
    
    public void Request() {  // 购买一个饮料
        state.Handle(this);
    }
} 

interface State {
    public void Handle(Context context);
}

class StateA implements State {  // 库存不为0的状态
    
    @Override
    public void Handle(Context context) {
        int count = context.getCount();
        
        if (count >= 1) {  // 库存不为0
            System.out.println("购买成功");  // 进行购买
            context.setCount(count - 1);  // 购买后库存-1
            
            if (context.getCount() == 0) {  // 判断当前库存是否需要补货
                context.setState(new StateB());  // 将当前贩卖机的状态更改为B
            } else {
                System.out.println("购买失败"); 
            }
        }
    }
}

class StateB implements State {  // 无货状态
    
    @Override
    public void Handle(Context context) {
        int count = context.getCount();
        
        if (count == 0) {
            System.out.println("购买失败!等待补货");
            
            count.setCount(5);  // 补货
            System.out.println("补货成功,请重新购买");
            context.setState(new StateA());  // 状态切换为有货状态
        }
    }
}
3)策略模式
a、适用范围
  • 定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换,使得算法可以独立于使用它们的客户而变化;
b、代码示例
public class StrategyPattern {
    
    public static void main(String[] args) {
        Strategy add = new AddStrategy();
        Strategy sub = new SubStrategy();
        Strategy mul = new MulStrategy();
        
        Operationtext context = new Operationtext(add);
        context.operation(2022, 528);
        
        context = new Operationtext(sub);
        context.operation(2022, 528);
        
        context = new Operationtext(mul);
        context.operation(2022, 528);
    }
}

class Operationtext {  // 环境
    private Strategy strategy;  // 策略对象的引用
    
    public Operationtext(Strategy strategy) {
        this.strategy = strategy;
    }
    
    public void Operation(int a, int b) {
        strategy.TowNumberOperation(a, b);
    }
}

interface Strategy {  // 策略对象
    public void TowNumberOperation(int a, int b);
}


class AddStrategy implements Strategy {
    
    @Override
    public void TowNumberOperation(int a, int b) {
        System.out.println(a + b);
    }
}

class SubStrategy implements Strategy {
    
    @Override
    public void TowNumberOperation(int a, int b) {
        System.out.println(a - b);
    }
}

class MulStrategy implements Strategy {
    
    @Override
        public void TowNumberOperation(int a, int b) {
        System.out.println(a * b);
    }
}
4)访问者模式
a、适用范围
  • 表示一个作用于某对象结构中的各元素的操作,它允许在不改变各元素的类的前提下定义作用于这些元素的新操作;
b、代码示例
public class VisitorPattern {
    public static void main(String[] args) {
        PersonStructure structure = new PersonStructure();
        
        Visitor1 visitor1 = new Visitor1();
        structure.Accept(visitor1);
        
        Visitor2 visitor2 = new Visitor2();
        structure.Accept(visitor2);
    }
}

interface Visitor {  // 访问者
    public void visitStudent(Student student);  // 访问学生
    public void visitTeacher(Teacher teacher);  // 访问老师
}

class Visitor1 implents Visitor {  // 访问者1
    
    @Override
    public void visitStudent(Student student) {
        // 在访问学生和访问老师中进行对象方法的操作即可,不需要在学生和老师类中进行定义
        System.out.println("访问者1访问学生:" + student.name);
    }
    
    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者1访问老师:" + teacher.name);
    }
}

class Visitor2 implents Visitor {  // 访问者2
    
    @Override
    public void visitStudent(Student student) {
        System.out.println("访问者2访问学生:" + student.name);
    }
    
    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者2访问老师:" + teacher.name);
    }
}

class PersonStructure {
    private List<Person> personList = new ArrayList<>();
    
    public PersonStructure() {
        personList.add(new Student("张三");
        personList.add(new Student("张三");
        personList.add(new Student("张三");
        
        personList.add(new Teacher("李老师");
        personList.add(new Teacher("陈老师");
        personList.add(new Teacher("王老师");
    }
    
    public void Accept(Visitor visitor) {  // 让访问者去访问所有对象
        for (person : personList) {
            person.Accept(visitor);
        }
    }
}

abstract class Person {
    private String name;
    
    public abstract void Accept(Visitor visitor);
}

class Student extends Person {
    
    public Student(String name) {
        this.name = name;
    }
    
    @Override
    public void Accept(Visitor visitor) {  // 接受访问的操作
        visitor.visitStudent(this);
    }
}

class Teacher extends Person {
    
    public Teacher(String name) {
        this.name = name;
    }
    
    @Override
    public void Accept(Visitor visitor) {  // 接受访问的操作
        visitor.visitTeacher(this);
    }
}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个写代码的修车工

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值