单例设计模式:
1、饿汉式
public class Demo { public static void main(String[] args){ Singleton1 singleton1 = Singleton1.getSingleton1(); //通过类调用接口 singleton1.print(); }}class Singleton1{ private Singleton1(){}; //将构造方法私有化,外部不能new对象 private static Singleton1 singlenton1 = new Singleton1(); //使用静态存储方式,只存一个对象,当类被加载时,singleton1对象就被创建,一直放在内存中,直到程序结束; public static Singleton1 getSingleton1(){ //将getSingleton1()方法设置为静态方法,让类可以调用,返回实例 return singlenton1; } public void print(){ System.out.println("测试"); } }
2、懒汉式(优先考虑)
已经优化过;
import java.io.Serializable;public class Demo { public static void main(String[] args){ Singleton1 singleton1 = Singleton1.getSingleton1(); //通过类调用接口 singleton1.print(); }}//让单例可以实现被序列化;class Singleton1 implements Serializable { //volatile 保证变量的一直性,取值的时候不会中寄存器中取,会从内存地址取值 private static volatile Singleton1 singleton1; //声明一个静态的实例,只存一次 //为了防止通过反射强制访问私有方法;,如果singleton1为空的话,就可以实例,如果程序已经运行了,不为空,就设置报错; private Singleton1(){ if (singleton1!=null){ throw new RuntimeException("此类已经被实例化;单例模式"); } }; //将构造方法私有化,外部不能new对象 public static Singleton1 getSingleton1(){ if(singleton1==null){ //解决多线程性能问题, synchronized (Singleton1.class){ if(singleton1==null){ //若果没有这个判断,当程序刚刚启动,如果两个多线程同时进入第一个if判断,那么之后,就会生成两个多个实例对象了 singleton1 = new Singleton1(); //创建实例,在getSingleton()方法调用时创建,程序结束后释放,多线程存在问题 } } } return singleton1; } public void print(){ System.out.println("测试"); }}
补充:通过使用构造方法私有化,加静态方法代替单例,例如工具类中的Math
不需要创建对象,静态方法一直加载在内存中,直到程序退出
public class Demo { public static void main(String[] args){ Singleton1.fun1(); //直接通过类调用方法 }}class Singleton1{ private Singleton1(){}; //将构造方法私有化,外部不能new对象 public static void fun1(){ System.out.println("方法一"); } public static void fun2(){ System.out.println("方法二"); } public static void fun3(){ System.out.println("方法三"); }}
单例和使用静态方法代替单例对比
1、使用单例,当执行方法时,如果有定义的变量,方法进栈,执行完毕后,出栈,变量销毁,优点:省内存,缺点:需要反复的调用,耗时
2、静态方法代替单例:优点:调用的时间快,缺点:一直加载内存中,不能被销毁,比较占内存
模板方法设计模式:
1、定义一个操作算法的骨架(每一个对象都必须实现的),而将一些可变部分的实现(可以根据自己的需求自定义)延迟到子类中
2、模板方法模式使子类可以不改变一个算法的结构即可重新定义该算法的某些特征
子类调用父类的方法,父类在调用子类的方法;(本质上在调用子类方法之前,先执行父类的方法(所有的子类都有一样的需求))
/** 需求在进行数据的增删改查的时候,每次都要判断用户是不是为管理员,如果为管理员,就可以执行操作 例如学校老师(管理员)对学生的管理。企业管理员对员工的管理,*/public class Demo { public static void main(String[] args){ TeacherandStudent user = new TeacherandStudent(); user.action("Admin","add"); //用户执行命令 user.action("Test","add"); }}abstract class Manage{ //所有的对象都需要执行的操作 public void action(String user,String method){ if("Admin".equals(user)){ excute(method); return; }else{ System.out.print("你没有权限,请您联系管理员"); return; } } abstract void excute(String method);}class TeacherandStudent extends Manage{ //老师和学生的页面都是一样的,只是老师这个用户有对学生进行修改的权限 public void excute(String method){ //老师和学生的业务逻辑不需要判断用户有没有添加和删除的权限了 if("add".equals(method)){ System.out.println("正在执行添加操作"); }else if("delete".equals(method)){ System.out.println("正在执行删除操作"); } }}class BossManage extends Manage{ public void excute(String method){ }}
另一种思路比较(静态代理模式),调用代理的方法,代理中调用需要实现类的方法
public class Demo { public static void main(String[] args) { Father father = new Father(); father.excute(new Son(),"add"); }}interface action{ void action(String option);}class Father{ public void excute(action obj,String option){ //判断该对象是否有权限(省略) obj.action(option); }}class Son implements action{ public void action(String option) { if ("add".equals(option)){ System.out.println("添加数据成功"); return; }if ("delete".equals(option)){ System.out.println("删除数据成功"); return; } }}
策略设计模式:
接口应用:
定义一系列算法,并将每一种算法封装起来可以相互替换使用;
策略模式让算法独立于使用它的客户,可以独立变化;
把可变的行为抽象出来,定义一系列算法,进行封装,让代码方便扩展,修改,易于维护
面向接口编程实例:
/** 不同的文件保存到不同的地方*/public class Demo { public static void main(String[] args){ User save = new User(); save.setISave(new FileSava()); save.loadfile("数据"); }}interface ISave{ public abstract void save();}class FileSava implements ISave{ public void save(){ System.out.println("文件保存到本地完毕"); };}class NetSava implements ISave{ public void save(){ System.out.println("文件保存到网络完毕"); };}abstract class BaseSava{ private ISave isave; //使用组合的方式,将BaseSava和ISava组合起来 public void setISave(ISave isave){ this.isave = isave; } public void loadfile(String data){ System.out.println("文件合法....."); this.isave.save(); }}class User extends BaseSava{ }
简单工厂设计模式:
利用工厂生产所需要的类。解耦;
public class Demo { public static void main(String[] args){ Product product = ProductFactory.getProduct("phone"); product.work(); }}class ProductFactory{ static Product getProduct(String name){ if("phone".equals(name)){ return new Phone(); }else if("compulter".equals(name)){ return new Computer(); } return null; }}interface Product{ void work();}class Phone implements Product{ public void work(){ System.out.println("手机开始工作"); }}class Computer implements Product{ public void work(){ System.out.println("手机开始工作"); }}
静态代理模式:
在运行前就已经将代理写好了
为其他对象提供一种代理以控制对这个对象的访问
被代理的代码有完整的业务实现,可以单独运行。而通过代理可以添加一些其他的需求。然后通过代理来控制被代理的业务实现。
public class Demo { public static void main(String[] args){ Proxy proxy = new Proxy(new Phone()); proxy.work(); }}interface Action{ void work();}class Phone implements Action{ //被代理 public void work(){ System.out.println("手机开始工作"); }}class Proxy implements Action{ //代理 private Action action; public Proxy(){} public Proxy(Action action){ this.action = action; } public void work(){ long starttime = System.currentTimeMillis(); this.action.work(); long endtime = System.currentTimeMillis(); System.out.println("一共耗时:"+(endtime - starttime)+"毫秒"); } }
动态代理模式:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Demo { public static void main(String[] args) { CreateProxy createproxy = new CreateProxy(); Customer customer = new Customer(); Subject subject = (Subject) createproxy.create(customer); subject.shopping(); //会调用invoke方法 }}interface Subject { void shopping();}class Customer implements Subject { @Override public void shopping() { System.out.println("付款,购买物品"); }}//用于动态生成一个代理对象class CreateProxy implements InvocationHandler { private Object target; //被代理对象,用Object接收 public Object create(Object target) { //创建代理对象 this.target = target; //newProxyInstance参数类加载器,接口数组,this,接口是动态加载的(可以调用多个接口) Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); return proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()); //可以用它来判断特定的方法执行不同的功能; System.out.println("正在挑选商品....."); System.out.println("已挑选好商品.....,等待客户确认订单"); method.invoke(target, args); System.out.println("订单完成"); return null; }}
不实现 InvocationHandler 接口(下面的案例采用内部类的写法)
public class Demo { public static void main(String[] args) { Test test = new Test(); CreateProxy createProxy = new CreateProxy(); TestInterface testInterface = (TestInterface) createProxy.getProxy(test); testInterface.test(); }}interface TestInterface{ void test();}class Test implements TestInterface{ public void test(){ System.out.println("test"); }}class CreateProxy{ public Object getProxy(final TestInterface obj){ Object object = Proxy.newProxyInstance(CreateProxy.class.getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("执行代理"); Object invoke = method.invoke(obj, args); return invoke; } }); return object; }}
静态代理和动态代理的对比
参考: 写的很详细
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
优点:代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合)
缺点:1、代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2、代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。
动态:在程序运行时运用反射机制动态创建而成。
优点:如果静态代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类,而动态代理,只需要一个代理类,在代理类中添加不同的代理方法(返回不同的代理对象)即可。
不需要实现委代理类的每一个实现方法,减少代码的冗余
适配器设计模式:
将一个类的接口转换成客户希望的另一个的接口
适配器使原本由于接口不兼容而不能工作的那些类可以一起工作
public class Demo { public static void main(String[] args){ work(new PowerAachieve()); //work(new PowerBachieve()); //接口A接受不了接口B Adapter adapter = new Adapter(new PowerBachieve()); //利用适配器接入接口A。接口B接入到适配器上即可 work(adapter); } public static void work(PowerA power){ //接口A(可以接受是适配器,不能接受接口B) power.insert(); }}interface PowerA{ void insert();}class PowerAachieve implements PowerA{ public void insert(){ System.out.println("接口A开始工作"); }}//适配器class Adapter implements PowerA{ //适配器必须继承接口B,将接口B接入到适配器上 private PowerB power; public Adapter(PowerB power){ this.power = power; } public void insert(){ this.power.connect(); }}interface PowerB{ void connect();}class PowerBachieve implements PowerB{ public void connect(){ System.out.println("接口B开始工作"); }}
适配器用途二
public class Demo { public static void main(String[] args){ work(new Dog()); } public static void work(Animal animal){ //接口Animal(可以接受是适配器) animal.run(); }}interface Animal{ void run(); void sing(); void swim(); void fly();}//class Dog implements Animal{// public void run(){};// public void sing(){};// public void swim(){// System.out.println("如果只要实现swim方法,但是需要将所有继承的方法都是实现(可以不写其代码)");// };// public void fly(){};//}//利用适配器实现所有的接口,其他的类直接继承适配器.这样的好处是不用每一个类都要实现所有的方法.abstract class Adapter implements Animal{ public void run(){}; public void sing(){}; public void swim(){}; public void fly(){};}class Dog extends Adapter{ public void run(){ System.out.println("我可以跑"); }}
装饰者设计模式:
public class Test { public static void main(String[] args){ Milk milk = new Milk(); Coffer coffer = new Coffer(milk); Coke coke = new Coke(coffer); System.out.println(coke.cost()+","+coke.desc()); }}interface Drink{ float cost(); String desc();}class Milk implements Drink{ @Override public float cost() { return 10f; } @Override public String desc() { return "牛奶"; }}abstract class Decorator implements Drink{ private Drink drink; public Decorator(Drink drink){ this.drink = drink; } @Override public float cost() { return this.drink.cost(); } @Override public String desc() { return this.drink.desc(); }}class Coffer extends Decorator{ public Coffer(Drink drink) { super(drink); } @Override public float cost() { return super.cost()+1.0f; } @Override public String desc() { return super.desc()+"加咖啡"; }}class Coke extends Decorator{ public Coke(Drink drink) { super(drink); } @Override public float cost() { return super.cost()+1.0f; } @Override public String desc() { return super.desc()+"加可乐"; }}
迭代器设计模式:
省略
观察者设计模式:
观察者模式定义了一个一对多的依赖关系,让一个或者多个观察者对象同时监听一个主题对象;这一个主题对象在状态上发生变化,就会通知所有依赖此对象的所欲的观察者对象;
import java.util.ArrayList;import java.util.List;public class Demo { public static void main(String[] args) { MessageSubject messageSubject = new Subject(); messageSubject.registerObserver(new User("小明")); User u = new User("小芳"); messageSubject.registerObserver(u);// messageSubject.notifyObserver(); messageSubject.setMessage("开炮..."); messageSubject.removeObserver(u); messageSubject.setMessage("继续开炮..."); }}interface MessageSubject{ //注册观察者 public void registerObserver(Observer o); //移除观察者 public void removeObserver(Observer o); //通知所有的观察者 public void notifyObserver(); public void setMessage(String message);}//观察者接口interface Observer{ public void print(String message);}class Subject implements MessageSubject{ private Observer observer; private String message; private ListobserverList = new ArrayList (); @Override public void registerObserver(Observer o) { observerList.add(o); } @Override public void removeObserver(Observer o) { observerList.remove(o); } public void setMessage(String message) { this.message = message; notifyObserver(); } @Override public void notifyObserver() { for (int i = 0; i < observerList.size(); i++) { observerList.get(i).print(message); } }}class User implements Observer{ private String name; public User(String name) { this.name = name; } @Override public void print(String message) { System.out.println(name+"已经接受消息:"+message+",准备处理"); }}