网站集约化建设的好处,专做艺术圈的网站,网站开发项目分析模板,一个网站如何做cdn加速1、工厂模式
1.1 工厂模式的由来
在现实生活中我们都知道
原始社会自给自足#xff08;没有工厂#xff09;农耕社会有了小作坊#xff08;简单工厂,如民间酒坊#xff09;工业革命后有了流水线#xff08;工厂方法#xff0c;自产自销#xff09;现代产业链中有代工…1、工厂模式
1.1 工厂模式的由来
在现实生活中我们都知道
原始社会自给自足没有工厂农耕社会有了小作坊简单工厂,如民间酒坊工业革命后有了流水线工厂方法自产自销现代产业链中有代工厂抽象工厂如富士康
我们的项目代码同样也是由简到繁一步一步迭代而来的但对于调用者来说却越来越简单化了
1.2 简单工厂模式
简单工厂模式Simple Factory Pattern是指由一个工厂对象决定创建哪一种产品类的实例但它不属于GoF的23种设计模式。 简单工厂模式适用于工厂类负责创建的对象较少的场景且客户端只需要传入工厂类的参数对于如何创建对象不需要关心。
举例
1、假设现在开设有Java架构、大数据、人工智能等课程。 2、我们有一个课程标准ICourse接口 3、创建一个Java课程的实现类
public interface ICourse {/*录制视频*/public void record();
}
package SimpleFactoryPattern;public class JavaCourse implements ICourse {Overridepublic void record() {System.out.println(录制Java课程);}
}public class Project1Test {public static void main(String[] args) {ICourse course new JavaCourse();course.record();}
}如果要进行业务扩展增加PythonCourse会怎么样
public class PythonCourse implements ICourse {Overridepublic void record() {System.out.println(录制python课程);}
}按照刚才方式如果业务扩展则需要继续增加PythonCourse甚至更多课程类则客户端的依赖会变得越来越臃肿。 因此可用简单工厂模式对其进行优化把课程的创建细节隐藏起来减弱客户端与其他类的依赖。 优化方案创建工厂类CourseFactory
/*** 创建工厂类*/
public class CourseFactory {public ICourse create(String name){if (java.equals(name)){return new JavaCourse();}else if (python.equals(name)){return new PythonCourse();}else {return null;}}public class Project2Test {//创建工厂类客户端调用方法public static void main(String[] args) {CourseFactory factory new CourseFactory();factory.create(java);factory.create(python);}
}但这种方式下如果业务继续扩展就要修改工厂中的create方法不符合开闭原则。 继续对其进行优化反射技术
public class CourseFactory {public ICourse create(String className){try {if (!(null className || .equals(className))){return (ICourse)Class.forName(className).newInstance();}}catch (Exception e){e.printStackTrace();}return null;}/*public ICourse create(Class? extends ICourse clazz){try {if(null ! clazz){return clazz.newInstance();}}catch (Exception e){e.printStackTrace();}return null;}*/
}public class Project3Test {public static void main(String[] args) {CourseFactory factory new CourseFactory();ICourse course1 factory.create(SimpleFactoryPattern.JavaCourse);course1.record();ICourse course2 factory.create(SimpleFactoryPattern.PythonCourse);course2.record();}/*public static void main(String[] args) {CourseFactory factory new CourseFactory();ICourse course1 factory.create(JavaCourse.class);course1.record();ICourse course2 factory.create(PythonCourse.class);course2.record();}*/
}使用这种方式
如果进行业务扩展无需修改create方法代码符合开闭原则。只能把ICourse及其子类作为参数传入工厂类可避免一些未知错误。
1.3 工厂方法模式
简单工厂模式缺点工厂类的职责过重不易于扩展过于复杂的产品结构。若每个课程的创建逻辑有区别随着产品增多会变得更不易维护。 工厂方法模式Factory Method Pattern是指定义一个创建对象的接口但让实现这个接口的类来决定实例化哪个类。 即创建工厂抽象类实现多个工厂不同工厂用来实例化不同类型对象。
优点可以解决产品扩展的问题。即根据“单一职责原则”对职能进行拆分Java课程由Java工厂创建Python课程由Python工厂创建。 缺点类的个数容易过多增加复杂度。
举例
以“简单工厂模式”中的例子进行拓展
public interface ICourseFactory {ICourse create();
}public class JavaCourseFactory implements ICourseFactory {Overridepublic ICourse create() {return new JavaCourse();}
}public class PythonCourseFactory implements ICourseFactory {Overridepublic ICourse create() {return new PythonCourse();}
}public class FactoryTest {public static void main(String[] args) {ICourseFactory factory new PythonCourseFactory();ICourse course factory.create();course.record();factory new JavaCourseFactory();course factory.create();course.record();}/*** 优点* 1.创建对象需要大量重复的代码* 2.客户端应用层不依赖于产品类的实例如何被创建、如何被实现等细节* 3.一个类通过其子类来指定创建哪个对象* 缺点* 1.类的个数容易过多增加复杂度* 2.增加了系统的抽象性和理解难度*/
}1.4 抽象工厂模式
抽象工厂模式Abstract Factory Pattern是指提供一个一系列相关或相互依赖对象的接口无须指定它们的具体类。
举例
现在有多门课程每门课程都有对应的笔记、视频等资料。若使用工厂方法模式怎么进行设计
Java课程Java笔记Java视频Python课程Python笔记Python视频课程笔记课程视频
则需要创建“Java笔记工厂”、“Python笔记工厂”、“Java视频工厂”、“Python视频工厂”等类的数量太多。 抽象工厂模式可通过为两个产品族Java课程、Python课程创建工厂类并在每个工厂类中描述两个产品等级笔记、视频来解决多维度对象的创建问题。 1、创建两个产品等级的接口INote和IVideo
public interface INote {void edit();
}public interface IVideo {void record();
}2、创建一个抽象工厂类CourseFactory
/*** 抽象工厂类CourseFactory*/
public interface CourseFactory {/*** 抽象工厂是主用户的主入口* 是Spring中应用得最广泛得一种设计模式* 易于扩展*/INote createNote();IVideo createVideo();
}3、创建Java产品族的视频类JavaVideo和笔记类JavaNote
/*** Java产品族的课堂笔记类JavaNote*/
public class JavaNote implements INote {Overridepublic void edit() {System.out.println(编写Java笔记);}
}/*** Java产品族的视频类JavaVideo*/
public class JavaVideo implements IVideo {Overridepublic void record() {System.out.println(录制Java视频);}
}4、创建Java产品族的具体工厂JavaCourseFactory
public class JavaCourseFactory implements CourseFactory {Overridepublic INote createNote() {return new JavaNote();}Overridepublic IVideo createVideo() {return new JavaVideo();}
}5、创建Python的工厂类视频类和笔记类与Java的创建方式类似
/*** Python产品族的课堂笔记类PythonNote*/
public class PythonNote implements INote {Overridepublic void edit() {System.out.println(编写Python笔记);}
}/*** Ptthon产品族的视频类PythonVideo*/
public class PythonVideo implements IVideo {Overridepublic void record() {System.out.println(录制Python视频);}
}public class PythonCourseFactory implements CourseFactory {Overridepublic INote createNote() {return new PythonNote();}Overridepublic IVideo createVideo() {return new PythonVideo();}
}6、客户端调用程序
public class AbstractTest {public static void main(String[] args) {JavaCourseFactory factory new JavaCourseFactory();factory.createNote().edit();factory.createVideo().record();PythonCourseFactory factory1 new PythonCourseFactory();factory1.createNote().edit();factory1.createVideo().record();}
}缺点扩展产品等级(如增加“源码”)时会不符合开闭原则。
2、单例模式详解
单例模式是指确保一个类在任何情况下都绝对只有一个实例并提供一个全局访问点。
2.1 饿汉式单例模式
饿汉式单例模式在类加载的时候就立即初始化并且创建单例对象。 绝对线程安全在线程还没出现之前就实例化了不可能存在访问安全问题。 优点没有加任何锁、执行效率高用户体验比懒汉式好。 缺点类加载的时候就初始化不管用不用都占着空间浪费了内存资源。 Spring中的IoC容器ApplicationContext就是饿汉式单例模式。
举例
/*** 饿汉单例模式*/
public class HungrySingleton {//先静态、后动态//先属性、后方法//先上后下public static final HungrySingleton hungrySingleton new HungrySingleton();private HungrySingleton(){System.out.println(构造方法);}
//先加载静态属性及代码块在加载构造方法和非静态private static HungrySingleton getInstance(){System.out.println(getInstance);return hungrySingleton;}
}
//饿汉式适用于单例对象较少的情况//饿汉式静态单例模式
//利用的是静态代码块机制
public class HungryStaticSingleton {private static final HungryStaticSingleton hungrySingleton;static {hungrySingleton new HungryStaticSingleton();}private HungryStaticSingleton(){}public static HungryStaticSingleton getInstance(){return hungrySingleton;}
}
//优点没有佳任何锁、执行效率高用户体验比懒汉式单例模式更好
//缺点类加载的时候久初始化不管用于不用都占用空间浪费了内存2.2 懒汉式单例模式双重检查锁
懒汉式单例模式的特点被外部类调用的时候内部类才会加载。 简单实现静态方法只有在被调用时才会加载。
/*** 懒汉单例模式*/
public class LazySimpleSingleton {private LazySimpleSingleton() {}//静态模块公共内存区域private static LazySimpleSingleton lazy null;public static LazySimpleSingleton getInstance () {if (lazy null) {lazy new LazySimpleSingleton();}return lazy;}}但是这种方式存在线程安全问题可以通过下面代码进行验证
/*** 线程类*/
public class ExectorThread implements Runnable {Overridepublic void run() {LazySimpleSingleton singleton LazySimpleSingleton.getInstance();System.out.println(Thread.currentThread().getName() :singleton);}
}public class LazySimpleSingletonTest {public static void main(String[] args) {Thread t1 new Thread(new ExectorThread());Thread t2 new Thread(new ExectorThread());t1.start();t2.start();System.out.println(End);}
}
//两个线程获取到的LazySimpleSingleton对象会出现不一致的可能如何解决懒汉式的线程不安全的问题 可以给getInstance()方法加上Synchronized线程同步关键字使方法变成同步线程方法。
public class LazySimpleSingleton {private LazySimpleSingleton() {}//静态模块公共内存区域private static LazySimpleSingleton lazy null;//用Synchronized修饰后若一个线程调用了此方法其他线程就不能够同时调用public Synchronized static LazySimpleSingleton getInstance () {if (lazy null) {lazy new LazySimpleSingleton();}return lazy;}}但这种方式下每次执行getInstance方法都会进行线程同步。若线程数量较多则CPU分配压力就会大大上升导致大批线程阻塞性能就会大幅下降 怎么解决Synchronized引起的性能问题 使用双重检查锁
public class LazySimpleSingleton {private LazySimpleSingleton() {}private static LazySimpleSingleton lazy null;public static LazySimpleSingleton getInstance () {if (lazy null) {Synchronized(LazySimpleSingleton.class){if (lazy null) {lazy new LazySimpleSingleton();//这不是一个原子指令分为以下三步//1、分配内存给这个对象//2、初始化对象//3、设置lazy指向刚分配的内存地址}}}return lazy;}} 此种情况下只有第一次调用getInstance方法时才会进行线程同步减少资源浪费。
3、原型模式详解
3.1 原型模式的应用场景
原型模式Prototype Pattern是指原型实例指定创建对象的种类并且通过复制这些原型创建新的对象。 主要适用于以下场景 1类初始化消耗资源较多。 2使用new生成一个对象需要非常繁琐的过程数据准备、访问权限等。 3构造方法比较复杂。 4在循环体中产生大量的对象。 在Spring中原型模式应用得非常广泛。例如使用IoC容器创建Bean对象时可设置bean对象的scope作用域为prototype来为同一个类创建多个不同的bean对象。
3.2 浅克隆
浅克隆只复制了值类型数据没有复制引用对象。 即所有的引用对象仍然指向原来的对象。
举例
public class JinGuBang implements Serializable {public float h 100;public float d 10;
}public class Monkey {public int height;public int weight;
}public class QiTianDaShengShallow extends Monkey implements Cloneable, Serializable {public JinGuBang jinGuBang;public QiTianDaShengShallow(){this.jinGuBang new JinGuBang();}Overrideprotected Object clone() throws CloneNotSupportedException{return this.shallowClone();}private QiTianDaShengShallow shallowClone(){QiTianDaShengShallow qi new QiTianDaShengShallow();qi.height this.height;qi.weight this.weight;qi.jinGuBang this.jinGuBang;return qi;}
}public class ShallowCloneTest {public static void main(String[] args) {QiTianDaShengShallow qi new QiTianDaShengShallow();try{QiTianDaShengShallow clone (QiTianDaShengShallow) qi.clone();System.out.println(浅克隆 (qi.jinGuBang clone.jinGuBang));} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}使用浅克隆获取到的jinGuBang属性依然指向原来的对象。
3.3深克隆
深克隆不只复制了值而且也复制了引用对象。 可通过多重循环遍历的方式逐层迭代复制引用对象的值自己试着实现。 也可使用串行化输入输出流的方式实现。
举例
public class QiTianDaShengDeep extends Monkey implements Cloneable, Serializable {public JinGuBang jinGuBang;public QiTianDaShengDeep(){this.jinGuBang new JinGuBang();}Overrideprotected Object clone() throws CloneNotSupportedException{return this.deepClone();}private QiTianDaShengDeep deepClone(){try {//将要复制的本对象串行化为二进制数据//此时会将对象中包含的对象也进行串行话ByteArrayOutputStream bos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(bos);oos.writeObject(this);//进行深克隆将二进制数据反串行化为对象实现ByteArrayInputStream bis new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois new ObjectInputStream(bis);QiTianDaShengDeep qi (QiTianDaShengDeep) ois.readObject();return qi;} catch (Exception e) {e.printStackTrace();return null;}}
}public class DeepCloneTest {public static void main(String[] args) {QiTianDaShengDeep qi new QiTianDaShengDeep();try{QiTianDaShengDeep clone (QiTianDaShengDeep) qi.clone();System.out.println(深克隆: (qi.jinGuBang clone.jinGuBang));}catch (CloneNotSupportedException e){e.printStackTrace();}}
}通过执行上面测试类可知 使用深克隆后克隆前后的jinGuBang属性不再指向同一对象。 深克隆会破坏单例可通过以下方式防止 1、不实现Cloneable接口 2、重写clone方法直接让其返回单例对象。
总结
简单工厂模式适用于工厂类负责创建的对象较少的场景且客户端只需要传入工厂类的参数对于如何创建对象不需要关心。 在工厂方法模式中用户只需要关心所需商品对应的工厂无须关心创作细节而且加入新的产品时符合开闭原则。 抽象工厂模式是指提供一个创建一系列相关或相互依赖对象的接口无须指定他们的具体类。 单例模式可以保证内存里只有一个实例减少了内存的开销还可以避免对资源的多重占用。 原型模式适用场景
类初始化消耗资源较多使用new生成一个对象需要非常繁琐的过程数据准备、访问权限等构造函数复杂 在循环体中含有大量的对象