2025年java实现面向对象的23种设计模式【超长预警,读完超过2小时】

java实现面向对象的23种设计模式【超长预警,读完超过2小时】这篇博客详细介绍了 Java 中面向对象的 23 种设计模式 包括创造型 结构型和行为型三大类别 每种模式都有详细的解释和代码示例

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

前置内容
面对对象的七个设计原则,包括单一职责原则开闭原则里氏替换原则依赖倒置原则接口隔离原则迪米特原则合成复用原则

设计模式分类
创建型模式,包括单例原型工厂抽象工厂建造者 ,共5 种模式。

结构型模式,包括代理适配器桥梁装饰外观享元组合,共7 种模式。

行为型模式,包括模板方法策略命令责任链状态观察者中介者迭代器访问者备忘录解释器 ,共11 种模式。

本文涉及一些简化的uml类图,用法可参照这篇博客,仅供参考。


设计原则
Design principles,设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

1、单一职责原则
Single Responsibility Principle(SRP),一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分。即一个类、接口、方法只负责一种职责。

2、开闭原则
Open Closed Principle(OCP),一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。需要做到用抽象构建框架,用实现扩展细节。

3、里氏替换原则
Liskov Substitution Principle(LSP),继承必须确保超类所拥有的性质在子类中仍然成立。

4、依赖倒置原则
Dependence Inversion Principle(DIP),高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。其核心思想是:要面向接口编程,不要面向实现编程。

5、接口隔离原则
Interface Segregation Principle(ISP),要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

6、迪米特原则
Law of Demeter(LoD),最少知道原则, 强调只和朋友说话,不和陌生人说话,这里的朋友指的是成员变量、方法的输入输出。如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

7、合成复用原则
Composite Reuse Principle(CRP),它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。



创造型模式

Creational Pattern,用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。

一、单例模式

Singleton Pattern,保证整个系统中一个类只有一个对象的实例,实现这种功能的方式就叫单例模式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
在这里插入图片描述

1、懒汉式

public class Singleton { 
   
    private static Singleton instance;

	private Singleton (){ 
   }

    public static Singleton getInstance() { 
   
        if (instance == null) { 
   
            instance = new Singleton();
        }
        return instance;
    }
} 

添加线程锁后:

public class Singleton { 
   
    private static Singleton instance;

	private Singleton (){ 
   }

    public static synchronized Singleton getInstance() { 
   
        if (instance == null) { 
   
            instance = new Singleton();
        }
        return instance;
    }
}

2、饿汉式

public class Singleton { 
   
    private static Singleton instance = new Singleton();

    private Singleton() { 
   
    }

    public static Singleton getInstance() { 
   
        return instance;
    }
}

3、双重校验锁

public class Singleton { 
   
    private volatile static Singleton singleton;

    private Singleton() { 
   
    }

    public static Singleton getSingleton() { 
   
        if (singleton == null) { 
   
            synchronized (Singleton.class) { 
   
                if (singleton == null) { 
   
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

4、静态内部类

public class Singleton { 
   
    private static class SingletonHolder { 
   
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() { 
   
    }

    public static final Singleton getInstance() { 
   
        return SingletonHolder.INSTANCE;
    }
}  

5、枚举

public enum Singleton { 
   
    INSTANCE;

    public void method() { 
   
    }
}

二、原型模式

Prototype Pattern,是用于创建重复的对象,同时又能保证性能。这种模式是实现了一个原型接口,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。当直接创建对象的代价比较大时,则采用这种模式。

1、浅拷贝的原型模式
对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用
在这里插入图片描述
代码示例

public class Prototype implements Cloneable{ 
   
    private String name;
    private String info;

    public Prototype(String name, String info) { 
   
        this.name = name;
        this.info = info;
    }

    @Override
    protected Prototype clone(){ 
   
        Prototype prototype=null;
        try { 
   
            prototype = (Prototype) super.clone();
        } catch (CloneNotSupportedException e) { 
   
            System.out.println("克隆失败");
            e.printStackTrace();
        }
        return prototype;
    }

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

    public void show(){ 
   
        System.out.println(name+info);
    }
}
    public static void main(String[] args) {
        Prototype p1 = new Prototype("小美", "在遛狗");
        Prototype p2 = p1.clone();
        p2.setName("小华");
        p1.show();
        p2.show();
    }

2、带原型管理器的原型模式

在这里插入图片描述

代码示例

//多边形抽象类
public abstract class RegularPolygon implements Cloneable { 
   
    protected String name;
    protected double side_length;

    public void setSide_length(float side_length) { 
   
        this.side_length = side_length;
    }

    @Override
    protected Object clone() { 
   
        Object clone = null;
        try { 
   
            clone = super.clone();
        } catch (CloneNotSupportedException e) { 
   
            System.out.println("克隆失败");
            e.printStackTrace();
        }
        return clone;
    }

    abstract void show();
}

//正三角类
public class EquilateralTriangle extends RegularPolygon { 
   
    public EquilateralTriangle() { 
   
        this.name = "EquilateralTriangle";
    }

    @Override
    void show() { 
   
        if (side_length==0){ 
   
            System.out.println("未指定边长");
        }else { 
   
            double area = Math.sqrt(3) * Math.pow(side_length, 2) / 4;
            System.out.printf("边长为%.2f的正三角形,周长为%.2f,面积为%.2f\n",side_length,3*side_length,area);
        }
    }
}

//正方形类
public class Square extends RegularPolygon { 
   
    public Square() { 
   
        this.name = "Square";
    }

    @Override
    void show() { 
   
        if (side_length==0){ 
   
            System.out.println("未指定边长");
        }else { 
   
            double area = Math.pow(side_length, 2);
            System.out.printf("边长为%.2f的正方形,周长为%.2f,面积为%.2f\n",side_length,4*side_length,area);
        }
    }
}

//原型管理器
public class PrototypeManager { 
   
    private HashMap<String, RegularPolygon> rps = new HashMap<String, RegularPolygon>();

    public PrototypeManager() { 
   
        rps.put("EquilateralTriangle", new EquilateralTriangle());
        rps.put("Square", new Square());
    }

    public void addShape(String key, RegularPolygon rp) { 
   
        rps.put(key, rp);
    }

    public RegularPolygon getShape(String key) { 
   
        RegularPolygon rp = rps.get(key);
        return (RegularPolygon) rp.clone();
    }
}

    public static void main(String[] args) {
        PrototypeManager pm=new PrototypeManager();
        RegularPolygon rp1=(EquilateralTriangle)pm.getShape("EquilateralTriangle");
        rp1.setSide_length(1);
        rp1.show();
        Square rp2=(Square)pm.getShape("Square");
        rp2.setSide_length(1);
        rp2.show();
    }

3、深拷贝的原型模式
对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。因Object类的clone方法只会拷贝对象中的基本的数据类型,故需要将原型模式中的数组、容器对象、引用对象等另行拷贝。当然,深拷贝的原型模式也可以结合原型管理器,这里不再赘述。

3.1、多层的浅复制
在这里插入图片描述

//业务类
public class Prototype implements Cloneable { 
   
    private String name;
    private String info;
    private SpaceTime spaceTime;

    public Prototype(String name, String info, SpaceTime spaceTime) { 
   
        this.name = name;
        this.info = info;
        this.spaceTime = spaceTime;
    }

    @Override
    protected Prototype clone() { 
   
        Prototype prototype = null;
        try { 
   
            prototype = (Prototype) super.clone();
        } catch (CloneNotSupportedException e) { 
   
            System.out.println("克隆失败");
            e.printStackTrace();
        }
        return prototype;
    }

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

    public void setInfo(String info) { 
   
        this.info = info;
    }

    public void setSpaceTime(SpaceTime spaceTime) { 
   
        this.spaceTime = spaceTime;
    }

    public void show() { 
   
        System.out.println(spaceTime.getWhen() + "," + name + "在" + spaceTime.getWhere() + info);
    }
}

//成员对象的类
public class SpaceTime implements Cloneable { 
   
    private String when;
    private String where;

    public SpaceTime(String when, String where) { 
   
        this.when = when;
        this.where = where;
    }

    public String getWhen() { 
   
        return when;
    }

    public String getWhere() { 
   
        return where;
    }

    public void setWhen(String when) { 
   
        this.when = when;
    }

    public void setWhere(String where) { 
   
        this.where = where;
    }

    @Override
    protected SpaceTime clone() throws CloneNotSupportedException { 
   
        SpaceTime spaceTime = null;
        try { 
   
            spaceTime = (SpaceTime) super.clone();
        } catch (CloneNotSupportedException e) { 
   
            System.out.println("时空克隆失败");
            e.printStackTrace();
        }
        return spaceTime;
    }
}

    public static void main(String[] args) throws CloneNotSupportedException {
        SpaceTime spaceTime = new SpaceTime("昨天", "操场");
        Prototype p1 = new Prototype("小明", "跑步",spaceTime);
        
        Prototype p2 = p1.clone();
        p2.setName("小友");
        SpaceTime spaceTime2 = spaceTime.clone();
        spaceTime2.setWhen("今天");
        p2.setSpaceTime(spaceTime2);

        p1.show();
        p2.show();
    }

3.2、利用序列化进行深拷贝
经序列化,对象将保存于文件或缓冲区中。反序列化时,会一视同仁的注入各种类型结构,就实现了深复制,甚至进一步的可以持久化保存。
在这里插入图片描述

//业务类
public class Prototype implements Serializable { 
   
    private String name;
    private String info;
    private SpaceTime spaceTime;

    public Prototype(String name, String info, SpaceTime spaceTime) { 
   
        this.name = name;
        this.info = info;
        this.spaceTime = spaceTime;
    }

    public SpaceTime getSpaceTime() { 
   
        return spaceTime;
    }

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

    public void setInfo(String info) { 
   
        this.info = info;
    }

    public void setSpaceTime(SpaceTime spaceTime) { 
   
        this.spaceTime = spaceTime;
    }

    public Prototype deepClone() throws IOException, ClassNotFoundException { 
   
        // 将对象写入字节缓冲流中
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);

        // 将对象从流中取出
        ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Prototype) ois.readObject();
    }

    public void show() { 
   
        System.out.println(spaceTime.getWhen() + "," + name + "在" + spaceTime.getWhere() + info);
    }
}

//成员对象的类
public class SpaceTime implements Serializable { 
   
    private String when;
    private String where;

    public SpaceTime(String when, String where) { 
   
        this.when = when;
        this.where = where;
    }

    public String getWhen() { 
   
        return when;
    }

    public String getWhere() { 
   
        return where;
    }

    public void setWhen(String when) { 
   
        this.when = when;
    }

    public void setWhere(String where) { 
   
        this.where = where;
    }
}

    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        SpaceTime spaceTime = new SpaceTime("昨天", "操场");
        Prototype p1 = new Prototype("小明", "跑步",spaceTime);

        Prototype p2 = p1.deepClone();
        p2.setName("小友");
        p2.getSpaceTime().setWhen("今天");
        
        p1.show();
        p2.show();
    }

三、工厂模式

Factory Pattern,工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

1、简单工厂模式
在这里插入图片描述
代码举例

//快餐类
public abstract class Snack { 
   
    protected abstract void produce();
}

//薯条类
public class Chips extends Snack { 
   
    @Override
    protected void produce() { 
   
        System.out.println("生产薯条");
    }
}

//汉堡类
public class Hamburger extends Snack{ 
   
    @Override
    protected void produce() { 
   
        System.out.println("生产汉堡包");
    }
}

//快餐店类
public class Noshery{ 
   
    public static Snack getProduct(String command){ 
   
        Snack snack = null;
        try { 
   
            if (command.equalsIgnoreCase("chips")) { 
   
                snack = new Chips();
            } else if (command.equalsIgnoreCase("hamburger")) { 
   
                snack = new Hamburger();
            } else { 
   
                throw new ClassNotFoundException("不能生产该产品");
            }
        } catch (ClassNotFoundException e) { 
   
            e.printStackTrace();
        }
        return snack;
    }
}

    public static void main(String[] args) {
        Noshery.getProduct("chips").produce();
        Noshery.getProduct("hamburger").produce();
    }

2、工厂方法模式
为实现开闭原则,增加一个全能类,形成工厂方法模式
在这里插入图片描述
代码举例

//快餐
public abstract class Snack { 
   
    protected abstract void produce();
}

//薯条
public class Chips extends Snack { 
   
    @Override
    protected void produce() { 
   
        System.out.println("生产薯条");
    }
}

//汉堡
public class Hamburger extends Snack{ 
   
    @Override
    protected void produce() { 
   
        System.out.println("生产汉堡包");
    }
}

//快餐店接口
public interface Noshery{ 
   
    public abstract Snack make();
}

//汉堡制造者
public class HambugerMaker implements Noshery { 
   
    @Override
    public Snack make() { 
   
        return new Hamburger();
    }
}

//薯条制造者
public class ChipMaker implements Noshery { 
   
    @Override
    public Snack make() { 
   
编程小号
上一篇 2025-03-20 23:11
下一篇 2025-04-02 08:21

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/104851.html