专业网站制作 广州番禺,大连网龙建站优化推广,济南做网站比较好的公司知道吗,上海外贸大厦单例模式
单例模式(Singleton Pattern)是java中最简单的设计模式之一。这种类型的设计模式属于创建型模式#xff0c;它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类#xff0c;该类负责创建自己的对象#xff0c;同时确保只有单个对象被创建。这个类提供了一…单例模式
单例模式(Singleton Pattern)是java中最简单的设计模式之一。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类该类负责创建自己的对象同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式可以直接访问不需要实例化该类的对象。 注意 1单例类只能有一个实例。 2单例类必须自己创建自己的唯一实例。 3单例类必须给所有其他对象提供这一实例。
优点 1在内存里面只有一个实例减少了内存的开销尤其是平凡创建和销毁实例。 2避免对文件的多重占用比如写文件操作。
缺点没有接口不能继承与单一职责原则冲突一个类应该只关心内部逻辑而不关心外面怎么样来实例化。
使用场景 1要求生产唯一序列号。 2Web中的计数器不用每次刷新都在数据库里加一次用单例先缓存起来。 3创建的一个对象需要消耗的资源过多比如I/O与数据库的链接等。
注意事项getInstance()方法中需要使用同步锁synchronized(Singleton.class)防止多线程同时进入造成instance被多次实例化。
实现 public class SingleObject {//创建SingleOject的一个对象private static SingleObject instance new SingleObject();//让构造器函数为private这样类就不会被实例化private SingleObject(){};//获取唯一可用的对象public static SingleObject getInstance(){return instance;}public void showMessage(){System.out.println(aaaa);}
}
Spring中定义的bean默认为单例模式保证每一个类中仅有一个实例并提供一个访问它的全局访问点。spring中的单例模式提供了全局访问点BeanFactory。但没有从构造器级别去控制单例这是因为spring管理的是任意的java对象。
单例模式的几种实现方式
1懒汉式线程不安全 这种方式是最基本的实现方式这种实现的最大的问题就是不支持多线程。因为没有加锁synchronized所以严格意义上不算单例模式。
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance null) { instance new Singleton(); } return instance; }
}2懒汉式线程安全 能够在多线程中很好的工作但是效率很低99%的情况下不需要同步。 优点第一次调用才初始化避免内存浪费。 缺点必须加synchronized才能保证单例但加锁会影响效率。
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance null) { instance new Singleton(); } return instance; }
}3饿汉式 这种方法比较常用但容易产生垃圾对象。 优点没有加锁执行效率会提高。 缺点类加载时就初始化浪费内存。 它基于classloader机制避免了多线程的同步问题不过instance在类装载时就实例化。
public class Singleton { private static Singleton instance new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; }
}4双检索/双重校验锁DCL即double-checked locking 这种方式采用双锁机制安全且在多线程情况下保持高性能。
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; }
}5登记式/静态内部类 这种方式能达到双检锁方式一样的功效但实现更简单。对静态域使用延迟初始化应该使用这种方式而不是双检锁方式。 这种方式同样使用了classLoader机制来保证初始化instace时只有一个线程它跟第三种方式不同的是第3种方式只要Singleton类被装载了那么instance就会被实例化而这种方式是Singleton类被撞在了instance不一定被初始化。因为SingletonHolder类没有被主动使用只有通过显式调用getInstance方法时才会显式装载Singleton类从而实例化instance。
public class Singleton {private static class SingletonHolder {private static finale Singleton INSTANCE new Singleton(); }private Singleton (){};public static final Singleton getInstance(){return SingletonHolder.INSTANCE;}
}6枚举 这是实现单例模式的最佳方法。它更简洁自动支持序列化机制防止被多次实例化。
public enum Singleton { INSTANCE; public void whateverMethod() { }
}总结一般情况下不建议使用第一种和第二种懒汉方式建议使用第三种饿汉方式只有在明确要实现lazy loading 效果时才会使用第五种登记方式。如果涉及到反序列化创建对象时可以尝试使用第六种枚举方式。
工厂模式
工厂模式Factory Pattern是Java中最常用的设计模式之一。这种类型的设计模式属于创建型模式。它提供了一种创建对象的最佳模式。在工厂模式中我们在创建对象时不会对客户端暴露创建逻辑并且通过使用一个共同的接口来指向新创建的对象。
优点 1一个调用者想创建一个对象只要知道其名称就可以了。 2扩展性高如果想要增加一个产品只要扩展一个工厂类就可以了。 3屏蔽产品的具体实现调用者只关心产品的接口。
注意事项作为一种创建类模式在任何需要生成复杂对象的地方都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式而简单对象特别是只需要通过new就可以完成创建的对象无需使用工厂模式。如果使用工程模式就需要引入一个工厂类会增加系统的复杂度。
使用场景 1日志记录器记录可以记录到本地磁盘、系统事件、远程服务器等用户可以选择日志记录到什么地方。 2数据库访问当用户不知道最后系统采用哪一类数据库时以及数据库可能有变化时。 3设计一个连接服务器的框架需要三个协议“POP3”,“IMAP”,“HTTP”可以把三个作为产品类实现同一个接口。
Spring中使用工厂模式通过BeanFactory、ApplicationContext创建Bean对象。
实现方式 我们创建一个Shape接口和实现Shape接口的实体类。下一步是定义工厂类ShapeFactory。 FactoryPatternDemo类使用ShapeFactory来获取Shape对象。它将向ShapeFactory传递信息CIRCLE / RECTANGLE / SQUARE以便获取它所需对象的类型。
步骤一创建一个接口
public insterface Shape{void draw();
}步骤二创建实现接口的实体类
public class Rectangle implements Shape{Overridepublic void draw() {System.out.println(Inside Rectangle::draw() method.);}
}public class Square implements Shape {Overridepublic void draw() {System.out.println(Inside Square::draw() method.);}
}public class Circle implements Shape {Overridepublic void draw() {System.out.println(Inside Circle::draw() method.);}
}步骤三创建一个工厂生成基于给定信息的实体类的对象
public class ShapeFactory{//使用getShape方法获取形状类型的对象public Shape getShape(String shapeType) {if (shapeType null) {return null;}if(shapeType.equalsIgnoreCase(CIRCLE)){return new Circle();} else if(shapeType.equalsIgnoreCase(RECTANGLE)){return new Rectangle();} else if(shapeType.equalsIgnoreCase(SQUARE)){return new Square();}return null;}
}步骤四使用该工厂通过传递
public class FactoryPatternDemo {public static void main(String[] args) {ShapeFactory shapeFactory new ShapeFactory();//获取 Circle 的对象并调用它的 draw 方法Shape shape1 shapeFactory.getShape(CIRCLE);//调用 Circle 的 draw 方法shape1.draw();//获取 Rectangle 的对象并调用它的 draw 方法Shape shape2 shapeFactory.getShape(RECTANGLE);//调用 Rectangle 的 draw 方法shape2.draw();//获取 Square 的对象并调用它的 draw 方法Shape shape3 shapeFactory.getShape(SQUARE);//调用 Square 的 draw 方法shape3.draw();}
}抽象工厂模式
抽象工厂模式Abstract Factory Pattern是围绕一个超级工厂创建其他工厂该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。 在抽象工厂模式中接口是负责创建一个相关对象的工厂不需要显式地指定它们的类每个生成的工厂都能按照工厂模式提供对象。
优点当一个产品族中的多个对象被设计成一起工作时它能保证客户端始终只使用同一个产品族中的对象。 缺点产品族扩展非常困难要增加一个系列的某一产品既要在抽象的Creator里加代码又要在具体的里面加代码。
使用场景 1QQ换皮肤一整套一起换 2生成不同操作系统的程序
注意事项 产品族难扩展 产品等级易扩展
策略模式
在策略模式中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式中我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的context对象。策略对象改变context对象的执行算法。
意图定义一系列的算法把他们一个个封装起来并且使他们可相互替换。 主要解决在多种算法相似的情况下使用if…else所带来的复杂和难以维护。 何时使用一个系统有许多类而区分它们的只是他们直接的行为。 如何解决将这些算法封装成一个一个的类任意的替换。
优点 1算法可以自由切换。 2避免使用多重条件判断。 3扩展性良好。
缺点 1策略类会增多。 2所有策略类都需要对外暴露。
Spring中资源访问接口Resource的设计是一种经典的策略模式。Resource接口是所有资源访问类所实现的接口Resource接口就代表资源访问策略但具体采用哪种策略实现Resource接口并不理会。客户端程序只和Resource接口耦合并不知道底层采用何种资源访问策略这样客户端可以再不同的资源访问策略之间自由切换。
实现方法 创建一个定义活动的Strategy接口和实现了Strategy
步骤一:
创建一个接口
public interface Strategy {public int doOperation(int num1, int num2);
}步骤二
创建接口的实现类
public class OperationAdd implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 num2;}
}public class OperationSubtract implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 - num2;}
}public class OperationMultiply implements Strategy{Overridepublic int doOperation(int num1, int num2) {return num1 * num2;}
}步骤三
创建Context类
public class Context {private Strategy strategy;public Context(Strategy strategy){this.strategy strategy;}public int executeStrategy(int num1, int num2){return strategy.doOperation(num1, num2);}
}步骤四
使用Context来 查看当它改变策略Strategy时的行为变化
public class StrategyPatternDemo {public static void main(String[] args) {Context context new Context(new OperationAdd()); System.out.println(10 5 context.executeStrategy(10, 5));context new Context(new OperationSubtract()); System.out.println(10 - 5 context.executeStrategy(10, 5));context new Context(new OperationMultiply()); System.out.println(10 * 5 context.executeStrategy(10, 5));}
}代理模式
在代理模式中一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中我们创建具有现有对象的对象以便向外界提供功能接口。