很多人都认为设计模式只是有一些,其实设计模式有23种设计模式例如最为简单的工厂设计模式、单例设计模式,创建者模式、原型设计模式、抽象工厂设计模式…其实这些都是一些简单的设计模式,一下为详细的设计模式
什么是设计模式
设计模式:设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因,简单的来说:
在某种环境下解决某种问题的解决方式,
通用,复用性强,进行处理问题的约束
设计模式的分类
设计模式之单例设计模式
单例设计模式只提供一个对象,确保一个类只有一个实例,自行实例化并向整个系统提供一个实例
单例设计模式分为:饿汉单例设计模式、懒汉单例设计模式、同步锁懒汉单例设计模式、双重锁单例设计模式、饿汉静态内部类单例设计模式、枚举设计模式
/**
* 主要写
* 双重锁单例设计模式
* 饿汉静态内部类单例设计模式
* 这两种最为安全效率高支持懒加载
*/
//饿汉静态内部类单例设计模式
public class HungrySingleton {
//1.创建私有化对象
private HungrySingleton() {
if (HungrySingle.hungry != null) {
throw new RuntimeException("防止反射攻击再次创建对象");
}
}
//2.创建内部引用
static class HungrySingle{
//内部类加载时加载当前对象
//volatile:修饰符修饰的多线程访问情况数据的同步性,这个涉及到jmm的虚拟机内存问题
//容易出现更改而出现的数据不一致的错误
private static volatile HungrySingleton hungry = new HungrySingleton();
}
//3.提供外部使用方法
public static HungrySingleton getInstance(){
return HungrySingle.hungry;
}
public Object readResolve() {
return HungrySingle.hungry;
}
}
//双重锁单例设计模式
public class LazySingleton {
//1.私有化构造器
private LazySingleton() {
if (lazySingleton != null) {
throw new RuntimeException("防止反射攻击再次创建对象");
}
}
//2.创建本类引用
private static volatile LazySingleton lazySingleton;
//3.提供外部使用方法
public static LazySingleton getInstance() {
//当第一次创建时本类引用为空才进行创建
if (lazySingleton == null) {
//容易出现多线程时创建对象,有一个线程进行创建时进行阻塞
synchronized (LazySingleton.class) {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
}
}
//多线程多次进入时直接将创建好的对象返回
return lazySingleton;
}
//防止反序列化的攻击,直接将创建好的对象进行返回
public Object readResolve() {
return lazySingleton;
}
}
设计模式之工厂设计模式
工厂设计模式是最为简单的设计模式,一个工厂为传入的全类名,跟据全类名创建实例对象
public static Object getInstance(String ClassName) throws ClassNotFoundException {
return Class.forName(ClassName).newInstance();
}
设计模式之抽象工厂设计模式
抽象工厂设计模式基于工厂设计模式的基础上增强了创建时多出零散的属性和方法,
简单来说就是一个总工厂分为多个工厂,而多个工厂处理多个对象的零散属性及方法
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象
//创建颜色接口
public interface Color {
void fill();
}
//创建形状接口
public interface Shape {
void draw();
}
//创建形状实现类
public class Circle implements Shape{
@Override
public void draw() {
System.out.println("Circle::draw() method");
}
}
//创建形状实现类
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("rectangle::draw() method");
}
}
//创建颜色实现类
public class Red implements Color {
@Override
public void fill() {
System.out.println("Red:fill() method");
}
}
//创建颜色实现类
public class Yellow implements Color{
@Override
public void fill() {
System.out.println("Yellow::fill() method");
}
}
/**
* 主要使用抽象工厂类处理其他工厂的功能
* 这里简写再次重写接口实现类调用方法传入全类名,总工厂进行处理其他工厂传入的方法
* 另外也使用了jdk8.0新特性在接口中创建静态方法进行调用
* 接口中写静态方法和类中写静态方法一样调用,就是接口中可以写方法体
*/
public interface GlobalFactory {
//jdk8.0新特性
static Object getShape(String shape) throws Exception {
if (shape == null) {
return null;
}
if (shape.equals("util.Rectangle")) {
return Class.forName(shape).newInstance();
}
if (shape.equals("util.Circle")) {
return Class.forName(shape).newInstance();
}
if (shape.equals("util.Red")) {
return Class.forName(shape).newInstance();
}
if (shape.equals("util.Yellow")) {
return Class.forName(shape).newInstance();
}
return null;
}
}
设计模式之建造者设计模式
建造者设计模式:使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
类似于抽象工厂设计模
与抽象工厂模式的区别是:建造者模式更加关注与零件装配的顺序
比如:一个公司中分为很多部门,将部门内分出很多角色,将多个角色及部门员工组合为一个整体部门,一个部门处理一件事,部门整体就类似于一个简单性的对象,中间分为很多零零散散的角色,将部门中的多个角色分为一个整体就可以体现一个部门,可以处理于多件事情
优点:1、建造者独立,易扩展。 2、便于控制细节风险
缺点:1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类
/**
* 定义电脑抽象类,进行外部传入操作系统
*/
public abstract class Computer {
protected String board;
protected String display;
protected String os;
protected Computer () {}
public void setBoard(String board) {
this.board = board;
}
public void setDisplay(String display) {
this.display = display;
}
public abstract void setOs();
@Override
public String toString() {
return "Computer{" +
"board='" + board + '\'' +
", display='" + display + '\'' +
", os='" + os + '\'' +
'}';
}
}
//重写电脑操作系统,进行赋值操作
public class Window extends Computer {
public Window() {}
@Override
public void setOs() {
//为抽象方法的OS进行赋值
super.os = "Window OS 12";
}
}
/**
* 扩展电脑中的方法
* 建造者更加关注与对象的零散顺序以及赋值参数
*/
public interface Builder {
void builderBoard(String board);
void builderDisplay(String display);
void builderOs();
//返回电脑方法
Computer com();
}
/**
* 重写扩展电脑方法
*/
public class BuilderImpl implements Builder {
//父类引用子类实现多态
Computer computer = new Window();
@Override
public void builderBoard(String board) {
computer.setBoard(board);
}
@Override
public void builderDisplay(String display) {
computer.setDisplay(display);
}
@Override
public void builderOs() {
//重写电脑已经封装好操作系统,直接调用就可以
computer.setOs();
}
@Override
public Computer com() {
return computer;
}
}
/**
* 负责构造Computer对象
*/
public class ComBuilder {
//扩展电脑的建造者属性
Builder builder;
//外部传入扩展电脑实现类
public ComBuilder (Builder builder) {
this.builder = builder;
}
//返回扩展电脑接口方法
public void construct(String board , String display) {
builder.builderBoard(board);
builder.builderDisplay(display);
builder.builderOs();
}
}
/**
* 测试代码
*/
@Test
public void builder() {
//有一些类似于代理设计模式,实现统一接口进行增强接口中的方法
//外部传入扩展接口方法
BuilderImpl builder = new BuilderImpl();
ComBuilder comBuilder = new ComBuilder(builder);
comBuilder.construct("英特尔主板","外星人显示器");
//获取扩展后的电脑
Computer com = builder.com();
System.out.println(com.toString());
}
执行结果
设计模式之原型设计模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。
当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建,我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用
可以提供与多次创建重复对象而使用的设计模式
/**
* 创建一个可克隆的类
*/
public abstract class Shape implements Cloneable{
private String id;
protected String type;
protected abstract void draw();
public Shape() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
//重写克隆方法
@Override
public Object clone() throws CloneNotSupportedException {
//返回克隆对象
return super.clone();
}
/**
* 重写父类的抽象方法
*/
public class Square extends Shape {
//为克隆类型赋值
public Square() {
super.type = "square";
}
@Override
public void draw() {
System.out.println("ExShape::draw() method");
}
}
/**
* 创建一个hash表进行存储重复克隆对象
*/
public class HashShape {
//hashtable:使其根据需要执行自动重新排序以增长表
//跟据计算hash值来添加数据,hash值最大的放在后面
private static Hashtable<String, Shape> hashtable = new Hashtable<>();
//传入对应id进行重复创建同一对象操作
public static Shape getShape(String shapeId) throws Exception {
Shape shape = hashtable.get(shapeId);
//返回克隆对象
return (Shape) shape.clone();
}
//给克隆对象赋值id操作
//形状都运行数据库查询,并创建该形状,类似于一个hash值作为一个索引
public static void loadShape() {
Square square = new Square();
square.setId("1");
//获取id值
hashtable.put(square.getId(),square);
}
}
/**
* 测试代码
*/
public class HashTest {
@Test
public void testShape() throws Exception {
HashShape.loadShape();
//调用赋值id
Square shape = (Square) HashShape.getShape("1");
shape.draw();
}
}
测试代码结果
如有哪一些不对,请大神们多多指教
感谢支持!!!