马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
工厂模式
一、工厂模式的总体长处
- 解耦:客户端与具体实现类解耦,符合“开闭原则”。
- 统一创建:对象创建交由工厂处置惩罚,便于会合控制。
- 增强可维护性:新增对象种类时不需要大改动调用代码。
- 便于扩展:易于管理产品族或产品等级结构。、
手写静态工厂模式,通过一个汽车静态工厂负责创建汽车
特点:
- 工厂类通过一个静态方法来返回差异的对象。
- 客户端通过传入参数决定创建哪个类。
✅ 长处:
- 实现简朴,结构清晰。
- 对客户端隐藏了对象的具体创建过程。
⚠️ 缺点:
- 不符合开闭原则(新增产品需修改 createCar() 方法)。
- 工厂职责过重,产品一多代码臃肿。
- public class StaticFactoryModel {
-
- public static void main(String[] args){
- car car=new CarFactory.createCar("Tesla");
- }
- interface car{
- void drive();
- }
- class Tesla implements car{
- @Override
- public void drive(){
- System.out.println("drive Tesla");
- }
- }
- class toyota implements car{
- @Override
- public void drive(){
- System.out.println("drive toyota");
- }
- }
- class CarFactory{
- public static car createCar(String type){
- switch(type){
- case"Tesla": return new Tesla();
- case"toyota":return new toyota();
- default:throw new IllegalArgumentException("UnKnow Car");
- }
- }
- }
复制代码 手写工厂方法模式
特点:
- 将创建对象的工作延迟到子类,通过差异工厂子类创建差异对象。
✅ 长处:
- 满意开闭原则,新增产品只需新增对应工厂。
- 结构清晰,职责单一,每个工厂只负责一种产品的创建。
⚠️ 缺点:
- 类的数目变多,增长体系复杂度。
- 只能生产单一类型的产品。
- package com;
- public class FactoryMethod {
- public static void main(String[] args) {
- phoneFactory factory=new iPhoneFactory();
- phone myphone=factory.createPhone();
- myphone.call();
- }
- }
- interface phone{
- public void call();
- }
- class iPhone implements phone{
- @Override
- public void call(){
- System.out.println("iPhone call");
- }
- }
- class Huawei implements phone{
- @Override
- public void call(){
- System.out.println("Huawei call");
- }
- }
- interface phoneFactory{
- public phone createPhone();
- }
- class iPhoneFactory implements phoneFactory{
- @Override
- public phone createPhone(){
- return new iPhone();
- }
- }
- class HuaweiFactory implements phoneFactory{
- @Override
- public phone createPhone(){
- return new Huawei();
- }
- }
复制代码 手写抽象工厂模式
✅ 特点:
- 一个工厂可以生产多个相干的产品(如电脑 + 操作体系)。
✅ 长处:
- 更强的扩展本事,可以生产“产品族”(多个相干产品)。
- 高度封装了产品的创建细节,对客户端透明。
⚠️ 缺点:
- 不易新增“新产品”(好比新加一个 Printer 接口)需修改所有工厂。
- 抽象程度更高,明白成本稍大。
- package com;
- public class AbstractFactory {
- public static void main(String[] args){
- ShowFactory factory=new WinFactory();
- Computee myCom=factory.createCom();
- Os myOs=factory.createOs();
- }
- }
- interface Computee{
- public void use();
- }
- interface Os{
- public void call();
- }
- class hp implements Computee{
- @Override
- public void use() {
- System.out.println("useing window");
- }
- }
- class AppleCom implements Computee{
- @Override
- public void use() {
- System.out.println("using apple");
- }
- }
- class window implements Os{
- @Override
- public void call() {
- System.out.println("calling window");
- }
- }
- class AppleOS implements Os{
- @Override
- public void call() {
- System.out.println("calling apple");
- }
- }
- interface ShowFactory{
- Computee createCom();
- Os createOs();
- }
- class WinFactory implements ShowFactory{
- @Override
- public Computee createCom() {
- return new hp();
- }
- @Override
- public Os createOs() {
- return new window();
- }
- }
- //..另外一个工厂对应行为
复制代码 计谋模式
计谋模式
上下文负责生成具体的计谋类而且负责与客户端交互
抽象计谋类为抽象脚色,通常由一个接口大概抽象类实现,给出所有的具体计谋类需要的接口
具体计谋类:是实现接口,提供具体算法大概举动
计谋模式长处:
- 算法解耦:将举动或算法封装在独立计谋类中,便于切换和扩展。
- 避免多重判断:通过多态替代 if-else 或 switch,结构更清晰。
- 符合开闭原则:新增计谋时无需改动已有代码,只需增长新计谋类。
- 可复用性高:差异上下文可复用同一个计谋类,提拔代码复用率
- package com;
- public class Strategy {
- }
- interface paymentStragegy{
- public void pay();
- }
- class wxpayMentStragegy implements paymentStragegy{
- @Override
- public void pay() {
- System.out.println("useing wxpay");
- }
- }
- class ApaymentStragegy implements paymentStragegy{
- @Override
- public void pay() {
- System.out.println("using apay");
- }
- }
- class context{
- String type=System.getenv("stragegy");
- public paymentStragegy mypayMent=null;
- public context(){
- switch(type){
- case "1":mypayMent=new ApaymentStragegy();
- case "2":mypayMent=new wxpayMentStragegy();
- default:mypayMent=new wxpayMentStragegy();
- }
- }
- }
复制代码 代理模式
代理模式(Proxy Pattern)是结构型设计模式的一种,
定义如下:
为其他对象提供一种代理以控制对这个对象的访问。
这里使用jdk代理实当代理模式
长处:
- 增强功能:在不修改原始对象的情况下增长额外逻辑(如权限校验、日记、事务等)。
- 解耦结构:将业务逻辑与通用功能分离,代码更清晰、职责更单一。
- 机动控制:可以在调用前后做一些处置惩罚,好比安全控制、延迟加载、访问控制等。
- 支持动态扩展:通过 JDK 动态代理可根据接口生成代理对象,运行时更机动。
- package com;
- import java.awt.*;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.lang.reflect.UndeclaredThrowableException;
- public class ProxyModel {
- }
- interface UserDao{
- public void add();
- public void delete();
- }
- class UserDaoImpl implements UserDao{
- @Override
- public void add() {
- System.out.println("adding");
- }
- @Override
- public void delete() {
- System.out.println("deleteling");
- }
- }
- class UserProxy implements InvocationHandler{
- Object object;
- public UserProxy(Object obb){
- object=obb;
- }
- public Object getProxy(){
- return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- System.out.println("代理加强前");
- Object invoke = method.invoke(object, args);
- System.out.println("代理加强后");
- return invoke;
- }
- }
复制代码
单例模式
定义:
单例模式就是一个类只有一个实例,而且还提供这个实例的全局访问点(避免一个全局使用的类频仍创建和烧毁,耗费体系资源)
设计要素
- 一个私有的构造函数(确保只能由单例类自己创建实例)
- 一个私有的静态变量(确保只有一个实例)
- 一个公有的静态函数(给调用者提供调用方法)
单例类的构造方法不让其他人修改和使用;而且单例类自己只创建一个实例,这个实例,其他人也无法修改和直接使用;然后单例类提供一个调用方法,想用这个实例,只能调用。这样就确保了全局只创建了一次实例。
六种实现方式
懒汉式(线程不安全)
先不创建实例,当第一次被调用的时间再创建实例,延迟了实例化,不需要使用该类就不会实例化,节省了体系资源
线程不安全,如果多个线程同时进入了lazyd==null,此时如果还没有实例化,多个线程就会进行实例化,导致实例化了多个实例
- package com;
- public class LazyD {
- private static LazyD lazyd;
- private LazyD(){
-
- }
- public static LazyD getUniqueInstance(){
- if(lazyd==null){
- lazyd=new LazyD();
- }
- return lazyd;
- }
- }
复制代码 饿汉式不管使用还是不使用这个实例,直接实例化好实例即可,然后如果需要使用的时间,直接调用方法即可
长处:提前实例化了,避免了线程不安全的问题
缺点:直接实例花了这个实例,不会再延迟实例化,如果体系没有使用这个实例,就会导致操作体系的资源浪费
- package com;
- public class HungryD {
- private static HungryD uniqueInstance=new HungryD();
-
- private HungryD(){};
-
- public static HungryD getUniqueInstance(){
- return uniqueInstance;
- }
- }
复制代码 懒汉式(线程安全)
和基本的懒汉式的区别就是在get方法上 加了一把 锁。如此一来,多个线程访问,每次只有拿到锁的的线程可以或许进入该方法,避免了多线程不安全问题的出现。
- package com;
- public class Singletion {
-
- private static Singletion uniqueInstance;
-
- private Singletion(){};
-
- public static synchronized Singletion getUniqueInstance(){
- if(uniqueInstance==null){
- uniqueInstance=new Singletion();
- }
- return uniqueInstance;
- }
- }
复制代码 双重校验锁实现(线程安全)
双重查抄锁定(Double-Check Locking)是一种对线程安全的懒汉式单例模式的优化。传统的线程安全懒汉式存在性能问题——即使单例已经创建,每次调用仍旧需要获取锁,导致性能下降。
而双重查抄锁定通过在加锁前先判断实例是否已存在,避免了不必要的锁开销:
- 如果实例已创建,直接返回实例,不进入加锁代码块,提拔了服从。
- 如果实例未创建,多个线程同时进入时,由于加锁机制,只有一个线程可以或许进入锁内创建实例,保证线程安全。
因此,只有在首次实例化时会发生线程壅闭,之后的调用都不会再产生锁竞争,从而实现了高效且安全的延迟初始化。
焦点就是对比懒汉式的线程安全版本有性能提拔
还有就是使用volatile关键字修饰uniqueInstance实例变量的缘故原由如下
实验 uniqueInstance = new Singleton(); 时,实际上分为三步:
- 为 uniqueInstance 分配内存
- 初始化 uniqueInstance
- 将 uniqueInstance 指向分配的内存所在
虽然正常顺序是 1 → 2 → 3,但 JVM 可能因指令重排导致实验顺序变为 1 → 3 → 2。
在单线程环境中这不会有问题,但在多线程环境下可能导致安全隐患:例如线程 A 实验了步骤 1 和 3,还未完成初始化(步骤 2),线程 B 看到 uniqueInstance 非空后直接使用它,结果是使用了未初始化的实例。
为避免这种情况,使用 volatile 关键字修饰 uniqueInstance,可以克制指令重排,确保多线程环境下实例的准确初始化和可见性,保证线程安全。
- package com;
- public class Singletion {
-
- private volatile static Singletion uniqueInstance;
-
- private Singletion(){};
-
- public static Singletion getUniqueInstance(){
- if(uniqueInstance==null){
- synchronized (Singletion.class){
- if(uniqueInstance==null){
- uniqueInstance=new Singletion();
- }
- }
- }
- return uniqueInstance;
- }
- }
复制代码 静态内部类实现(线程安全)
- 静态内部类 SingletonHolder 不会在类加载时初始化,只有在首次调用 getUniqueInstance() 方法并访问 SingletonHolder.INSTANCE 时才会被加载。
- 此时 JVM 会保证 INSTANCE 的初始化过程是线程安全的,而且 仅实验一次。
- 由于类加载机制的特性,JVM 会通过 类初始化锁(Class Initialization Lock) 确保 INSTANCE 的唯一性,无需额外同步代码。
- 懒加载:实例仅在需要时创建,节省资源。
- 线程安全:依赖 JVM 的类加载机制,无需双重查抄锁(DCL)或 synchronized。
- 高性能:无锁竞争,访问服从高
- package com;
- public class Singletion {
- private Singletion(){};
- private static class SingletionHolder{
- private static final Singletion INSTANCE=new Singletion()l
- }
- public static Singletion getUniqueInstance(){
- return SingletionHolder.INSTANCE;
- }
- }
复制代码 枚举类实现(线程安全)
枚举类的创建就是线程安全的,任何情况下都是单例的
枚举实现单例时,其实例的创建由 JVM 保证线程安全,且天然是单例。
长处
- 写法简便
- 天然线程安全
- 主动防止反射和反序列化攻击
关于反序列化问题
- 序列化:将 Java 对象转换为字节序列
- 反序列化:根据字节序列重建 Java 对象
通例单例模式在反序列化时可能会创建新的实例,破坏单例性。
为了避免这一问题,通常需要重写 readResolve() 方法来确保反序列化返回同一个实例:
- package com;
- public enum Singletion {
- INSTANCE;
- // 添加业务逻辑方法
- public void using() {
- // 实际功能逻辑写在这里
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |