前言
简说设计模式。
一、设计模式的要素
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);
}
}