1、单例模式
单例模式是指某个类只有一个实例存在。
饿汉式
public class Singleton {
private static Singleton singleton=new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
懒汉式
public class Singleton {
private static volatile Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(singleton==null){
synchronized (Singleton.class){
if(singleton==null)
singleton=new Singleton();
}
}
return singleton;
}
}
volatile作用:禁止处理器重排序。
java内存模型(jmm)并不限制处理器重排序,singleton=new Singleton()并不是原子语句,在执行时需要经历三大步骤:
(1) 为对象分配内存
(2) 初始化实例对象
(3) 将对象的内存地址赋值给singleton
如果一个线程的执行顺序是(1)(3)(2),当这个线程执行到(3)时,singleton就不为null了,这时另一个线程判断不为null就直接返回了,而此时并没有初始化,就会产生错误。
2、工厂模式、抽象工厂模式
工厂模式:自己不创建对象,将对象的创建权交给工厂。可以简单理解为平时我们用到一个对象,就会去new一个对象,而工厂模式相当于加了一个中间层,我们不再直接new对象,而是通过工厂去new对象,然后返回给我们。
import sun.security.provider.SHA;
/**
* Created by Administrator on 2020/4/13.
*/
public class TestFactory {
public static void main(String[] args) {
ShapeFactory shapeFactory=new ShapeFactory();
Shape rectangle=shapeFactory.getShape("RECTANGLE");
rectangle.draw();
Shape square=shapeFactory.getShape("SQUARE");
square.draw();
}
}
interface Shape{
public void draw();
}
class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("Rectangle draw method");
}
}
class Square implements Shape{
@Override
public void draw() {
System.out.println("Square draw method");
}
}
class ShapeFactory{
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}else{
return null;
}
}
}
抽象工厂模式
所谓抽象工厂模式,就是相当于有一个超级工厂来创建工厂,然后再由工厂创建对象。
import java.util.Comparator;
/**
* Created by Administrator on 2020/4/13.
*/
public class testAbstractFactory {
public static void main(String[] args) {
AbstractFactory computerFactory=FactoryProducer.getFactory("COMPUTER");
AbstractFactory phoneFactory=FactoryProducer.getFactory("PHONE");
Computer lianXiang=computerFactory.getComputer("LIANXIANG");
lianXiang.print();
Computer dell=computerFactory.getComputer("DELL");
dell.print();
Phone huawei=phoneFactory.getPhone("HUAWEI");
huawei.print();
Phone xiaomi=phoneFactory.getPhone("XIAOMI");
xiaomi.print();
}
}
interface Computer{
public void print();
}
class LianXiang implements Computer{
public void print(){
System.out.println("LianXiang print method");
}
}
class Dell implements Computer{
public void print(){
System.out.println("Dell print method");
}
}
interface Phone{
public void print();
}
class Huawei implements Phone{
public void print(){
System.out.println("Huawei print method");
}
}
class Xiaomi implements Phone{
public void print(){
System.out.println("Xiaomi print method");
}
}
abstract class AbstractFactory{
abstract Computer getComputer(String computerType);
abstract Phone getPhone(String phoneType);
}
class FactoryProducer{
public static AbstractFactory getFactory(String type){
if(type.equalsIgnoreCase("COMPUTER")){
return new ComputerFactory();
}else if(type.equalsIgnoreCase("PHONE")){
return new PhoneFactory();
}else{
return null;
}
}
}
class ComputerFactory extends AbstractFactory{
public Computer getComputer(String computerType){
if(computerType.equalsIgnoreCase("LIANXIANG")){
return new LianXiang();
}else if(computerType.equalsIgnoreCase("DELL")){
return new Dell();
}else{
return null;
}
}
public Phone getPhone(String phoneType){
return null;
}
}
class PhoneFactory extends AbstractFactory{
@Override
Computer getComputer(String computerType) {
return null;
}
@Override
Phone getPhone(String phoneType) {
if(phoneType.equalsIgnoreCase("HUAWEI")){
return new Huawei();
}else if(phoneType.equalsIgnoreCase("XIAOMI")){
return new Xiaomi();
}else{
return null;
}
}
}
3、代理模式
代理模式:即提供了对目标对象的另外访问方式,即通过代理对象访问目标对象。代理对象是对目标对象的扩展,并会调用目标对象。
-
静态代理
目标对象和代理对象需要实现相同的接口,通过调用相同的方法来调用目标对象的方法。
优点:可以在不改变目标类的前提下,对目标类进行功能扩展。
缺点:代理类和目标类要实现同样的接口,对于不同的目标类我们需要创建不同的代理类,另外当接口中增加方法时,目标类和代理类都需要维护,比较麻烦。
/**
* Created by Administrator on 2020/4/13.
*/
public class testStaticProxy {
public static void main(String[] args) {
ConsolePrinter consolePrinter=new ConsolePrinter();
StaticProxy staticProxy=new StaticProxy(consolePrinter);
staticProxy.print();
}
}
interface Printer{
void print();
}
class ConsolePrinter implements Printer{
@Override
public void print() {
System.out.println("ConsolePrinter print method");
}
}
class StaticProxy implements Printer{
private Printer target;
StaticProxy(Printer target){
this.target=target;
}
@Override
public void print() {
System.out.println("StaticProxy print method start");
target.print();
System.out.println("StaticProxy print method end");
}
}
-
动态代理
也称为JDK代理或者接口代理,代理类不需要实现接口,通过JDK的API,在内存中动态的生成代理对象。但是目标类一定要实现接口,否则无法实现JDK代理。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by Administrator on 2020/4/13.
*/
public class testJdkProxy {
public static void main(String[] args) {
Printer consolePrinter=new ConsolePrinter();
ProxyFactory proxyFactory1=new ProxyFactory(consolePrinter);
Printer proxy1=(Printer) proxyFactory1.getProxyFactory();
proxy1.print();
}
}
class ProxyFactory{
private Object target;
ProxyFactory(Object target){
this.target=target;
}
public Object getProxyFactory(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start");
Object ret=method.invoke(target,args);
System.out.println("end");
return ret;
}
});
}
}
-
cglib代理
JDK代理虽然不需要代理类实现目标类相同的接口,但是目标类必须要实现接口,有的类可能没有实现任何接口,是一个非常简单的类,这时候可以采用cglib代理。cglib代理也称为子类代理,它是在内存中构建一个子类对象从而实现对目标对象的代理。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* Created by Administrator on 2020/4/13.
*/
public class testCglibProxy {
public static void main(String[] args) {
User user=new User();
CglibProxyFactory cglibProxyFactory=new CglibProxyFactory(user);
User userProxy=(User) cglibProxyFactory.getProxyInstance();
userProxy.sayHello();
}
}
class User{
void sayHello(){
System.out.println("User sayHello");
}
}
class CglibProxyFactory implements MethodInterceptor{
private Object target;
CglibProxyFactory(Object target){
this.target=target;
}
public Object getProxyInstance(){
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("start");
Object ret=method.invoke(target,objects);
System.out.println("end");
return ret;
}
}
4、装饰者模式
装饰者模式用于给对象动态的添加一些职责,而无需改变原来的类。装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为。
/**
* Created by Administrator on 2020/4/13.
*/
public class testDecorator {
public static void main(String[] args) {
Drink coffee=new Coffee();
System.out.println(coffee.getIngredients());
coffee=new WithMilk(coffee);
System.out.println(coffee.getIngredients());
coffee=new WithSugar(coffee);
System.out.println(coffee.getIngredients());
}
}
interface Drink{
double getCost();
String getIngredients();
}
class Coffee implements Drink{
public double getCost() {
return 1;
}
public String getIngredients() {
return "coffee";
}
}
abstract class DrinkDecorator implements Drink{
private Drink drink;
DrinkDecorator(Drink drink){
this.drink=drink;
}
public double getCost() {
return drink.getCost();
}
public String getIngredients() {
return drink.getIngredients();
}
}
class WithMilk extends DrinkDecorator {
WithMilk(Drink drink) {
super(drink);
}
@Override
public double getCost() {
double additionalCost=0.5;
return super.getCost()+additionalCost;
}
@Override
public String getIngredients() {
String ingredients="milk";
return super.getIngredients()+","+ingredients;
}
}
class WithSugar extends DrinkDecorator{
WithSugar(Drink drink) {
super(drink);
}
@Override
public double getCost() {
double additionalCost=0.3;
return super.getCost()+additionalCost;
}
@Override
public String getIngredients() {
String ingredients="sugar";
return super.getIngredients()+","+ingredients;
}
}