网站模块顺序调整微商引流的最快方法是什么
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生成一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数复杂
在循环体中含有大量的对象