设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。
一.设计模式的分类
根据设计模式的参考书Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素)中提到 的,总共有23种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。
创建型模式:
工厂方法模式(Factory Method Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
原型模式(Prototype Pattern)
构建器模式(Builder Pattern)
结构型模式:
适配器模式(Adapter Pattern)
桥接模式(Bridge Pattern)
组合模式(Composite Pattern)
装饰器模式(Decorator Pattern)
外观模式(Facade Pattern)
享元模式(Flyweight Pattern)
代理模式(Proxy Pattern)
行为型模式:
职责链模式(Chain of Responsibility Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
备忘录模式(Memento Pattern)
中介者模式(Mediator Pattern)
观察者模式(Observer Pattern)
访问者模式(Visitor Pattern)
模板模式(Template Pattern)
策略模式(Strategy Pattern)
状态模式(State Pattern)
命令模式(Command Pattern)
二.设计模式的六大原则
1.单一职责原则
2.开放封闭原则
3.李氏替换原则
4.依赖倒置原则
5.接口隔离原则
6.迪米特原则(最少知识法则)
三.设计模式实现(Java)
工厂模式可以分为简单工厂模式,工厂方法模式和抽象工厂模式,其中简单工厂模式不属于GOF(Gang Of Four)提出的23种设计模式之一。
1.简单工厂模式
简单工厂模式:创建一个工厂类,对实现了同一接口的类进行实例创建。简单工厂模式的实质是有一个工厂类,根据传入的参数,动态的决定应该创建哪一个产品类(这些产品继承同一个类或实现同一个接口)的实例
简单工厂模式代码
这里我们以加减乘除运算为例,来创建代码。
创建一个运算类的父类Operation.java
public class Operation {
private double num1;
private double num2;
private double result = 0d;
public double getNum1() {
return num1;
}
public void setNum1(double num1) {
this.num1 = num1;
}
public double getNum2() {
return num2;
}
public void setNum2(double num2) {
this.num2 = num2;
}
public double getResult(){
return result;
}
}
创建加减乘除运算类,继承Operation.java
加法类AddOperation.java
public class AddOperation extends Operation {
public double getResult(){
return this.getNum1()+this.getNum2();
}
}
减法类SubOperation.java
public class SubOperation extends Operation {
public double getResult(){
return this.getNum1()-this.getNum2();
}
}
乘法类MulOperation.java
public class MulOperation extends Operation {
public double getResult(){
return this.getNum1()*this.getNum2();
}
}
除法类DivOperation.java
public class DivOperation extends Operation {
public double getResult(){
if(this.getNum2() == 0){
System.out.println("除数不能为0");
return 0;
}
return this.getNum1()/this.getNum2();
}
}
工厂类OperationFactory.java
public class OperationFactory {
public Operation produceOperation(String opType){
Operation operation = null;
if("+".equals(opType)){
operation = new AddOperation();
}else if("-".equals(opType)){
operation = new SubOperation();
}else if("*".equals(opType)){
operation = new MulOperation();
}else if("/".equals(opType)){
operation = new DivOperation();
}else{
System.out.print("请输入正确的操作字符!");
}
return operation;
}
}
客户端代码FactoryTest.java
public class FactoryTest {
public static void main(String[] args){
OperationFactory operationFactory = new OperationFactory();
Operation add = operationFactory.produceOperation("+");
Operation sub = operationFactory.produceOperation("-");
Operation mul = operationFactory.produceOperation("*");
Operation div = operationFactory.produceOperation("/");
add.setNum1(12);
add.setNum2(3);
sub.setNum1(12);
sub.setNum2(3);
mul.setNum1(12);
mul.setNum2(3);
div.setNum1(12);
div.setNum2(3);
System.out.println("加法操作结果为:"+add.getResult());
System.out.println("减法操作结果为:"+sub.getResult());
System.out.println("乘法操作结果为:"+mul.getResult());
System.out.println("除法操作结果为:"+div.getResult());
}
}
运行结果
根据开闭原则分析下简单工厂模式。当客户不再满足现有的计算类型的时候,想要增加一种新型的运算类型(比如求平方)运算,只要新增一种运算类型的子类即可;但是针对工厂类型,每增加一种新的运算类型,都要在工厂类中增加相应的创建业务逻辑(produceOperation(opType)),这显然是违背开闭原则的。于是为了解决这种现象,产生了工厂方法模式。
2.工厂方法模式
工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
定义一个工厂接口IOperationFactory.java
public interface IOperationFactory {
public Operation produceOperation();
}
定义具体的工厂类(加减乘除等,每个运算类型对应一个工厂类)
加法工厂类AddFactoryImpl.java
public class AddFactoryImpl implements IOperationFactory {
public Operation produceOperation(){
return new AddOperation();
}
}
减法工厂类SubFactoryImpl.java
public class SubFactoryImpl implements IOperationFactory {
public Operation produceOperation(){
return new SubOperation();
}
}
乘法工厂类MulFactoryImpl.java
public class MulFactoryImpl implements IOperationFactory {
public Operation produceOperation(){
return new MulOperation();
}
}
除法工厂类DivFactoryImpl.java
public class DivFactoryImpl implements IOperationFactory {
public Operation produceOperation(){
return new DivOperation();
}
}
客户端代码
package com.ldi.design.FactoryPartternsDemo.SimpleFactoryDemo;
public class FactoryTest {
public static void main(String[] args){
IOperationFactory addFactory = new AddFactoryImpl();
IOperationFactory subFactory = new SubFactoryImpl();
IOperationFactory mulFactory = new MulFactoryImpl();
IOperationFactory divFactory = new DivFactoryImpl();
Operation add = addFactory.produceOperation();
Operation sub = subFactory.produceOperation();
Operation mul = mulFactory.produceOperation();
Operation div = divFactory.produceOperation();
add.setNum1(12);
add.setNum2(4);
sub.setNum1(12);
sub.setNum2(4);
mul.setNum1(12);
mul.setNum2(4);
div.setNum1(12);
div.setNum2(4);
System.out.println("加法操作结果为:"+ add.getResult());
System.out.println("减法操作结果为:"+sub.getResult());
System.out.println("乘法操作结果为:"+mul.getResult());
System.out.println("除法操作结果为:"+div.getResult());
}
}
运行结果
工厂方法模式,将工厂类抽象出一个接口,该接口只有一个方法就是创建抽象产品的工厂方法。然后所有要生产具体类的工厂,实现这个接口。这样,一个简单工厂模式的工厂类,变成一个工厂抽象接口,和多个具体生成对象的工厂。因此,如果增加一种新的运算类型“求平方”,则不需要修改原有的工厂类,只需要增加相应的运算类和相应的工厂类即可。工厂方法将简单工厂的内部逻辑判断移到客户端进行。新增功能时,之前是修改工厂类,现在只需要修改客户端类。
3.抽象工厂模式
抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
抽象工厂模式的工厂类在创建产品类对象时可以创建一系列相关产品类的对象,而工厂方法模式在创建产品类时,创建一系列产品当中的一种产品类对象。
(声明:本文为个人学习笔记,观点非原创。如有问题,欢迎讨论。)