节省内存。
public class SingleMode {
private static volatile SingleMode singleMode = null;//懒汉式
private SingleMode() {
}
public static SingleMode getInstance() {
if (singleMode == null) {
synchronized (SingleMode.class) {
if (singleMode == null) {
singleMode = new SingleMode();
}
}
}
return singleMode;
}
}
将创建实例的工作与使用实例的工作分开,用户不再关心对象是如何创建的,只需要知道工厂api就可以得到对象了。
interface Sender{
void send();
}
class MailSender implements Sender{
@Override
public void send() {
System.out.println("发送邮件信息!");
}
}
class SmsSender implements Sender{
@Override
public void send() {
System.out.println("发送短信消息!");
}
}
class SenderFactory {
public static Sender newMailSender(){
return new MailSender();
}
public static Sender newSmsSender(){
return new SmsSender();
}
}
class FactoryMode{
public static void main(String[] args) {
Sender sender = SenderFactory.newMailSender();
Sender sender1 = SenderFactory.newSmsSender();
sender.send();
sender1.send();
}
}
SenderFactory维护麻烦,不优雅,工厂方法模式优化。
interface Sender{
void send();
}
class MailSender implements Sender{
@Override
public void send() {
System.out.println("发送邮件信息!");
}
}
class SmsSender implements Sender{
@Override
public void send() {
System.out.println("发送短信消息!");
}
}
interface Factory{
Sender createSender();
}
class MailSenderFactory implements Factory{
@Override
public Sender createSender() {
return new MailSender();
}
}
class SmsSenderFactory implements Factory{
@Override
public Sender createSender() {
return new SmsSender();
}
}
class FactoryMethodMode{
public static void main(String[] args) {
Sender sender = new MailSenderFactory().createSender();
Sender sender1 = new SmsSenderFactory().createSender();
sender.send();
sender1.send();
}
}
但是,如果想把Sender分类处理(4G对应一个Sender,5G对应一个Sender)或者实际情况中必须要分类处理呢?抽象工厂模式(工厂方法模式属于抽象工厂,是抽象工厂的一种特例)。
interface SenderA {
void send();//4G发送
}
interface SenderB {
void send();//5G发送
}
class MailSender implements SenderA {
@Override
public void send() {
System.out.println("4G发送邮件信息!");
}
}
class SmsSender implements SenderA {
@Override
public void send() {
System.out.println("4G发送短信消息!");
}
}
class NewMailSender implements SenderB {
@Override
public void send() {
System.out.println("5G发送邮件消息!");
}
}
class NewSmsSender implements SenderB {
@Override
public void send() {
System.out.println("5G发送短信消息!");
}
}
interface Factory {
SenderA createSenderA();
SenderB createSenderB();
}
class MailSenderFactory implements Factory {
@Override
public SenderA createSenderA() {
return new MailSender();
}
@Override
public SenderB createSenderB() {
return new NewMailSender();
}
}
class SmsSenderFactory implements Factory {
@Override
public SenderA createSenderA() {
return new SmsSender();
}
@Override
public SenderB createSenderB() {
return new NewSmsSender();
}
}
class AbstractFactoryMode {
public static void main(String[] args) {
MailSenderFactory mailSenderFactory = new MailSenderFactory();
SmsSenderFactory smsSenderFactory = new SmsSenderFactory();
mailSenderFactory.createSenderA().send();
mailSenderFactory.createSenderB().send();
smsSenderFactory.createSenderA().send();
smsSenderFactory.createSenderB().send();
}
}
通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,扩展目标对象的功能。
遵循编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需修改,可以通过代理的方式来扩展该方法。
interface UserDao{
void save();
}
class UserDaoImpl implements UserDao{
@Override
public void save() {
System.out.println("保存了数据...");
}
}
class UserDaoImplProxy implements UserDao{
UserDao userDao;
public UserDaoImplProxy(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void save() {
System.out.println("--开启事务");
userDao.save();
System.out.println("--关闭事务");
}
}
class StaticProxyModeMain{//静态代理模式
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
UserDaoImplProxy userDaoImplProxy = new UserDaoImplProxy(userDao);
userDaoImplProxy.save();
}
}
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.动态代理优化。
代理对象是利用JDK的API,动态的在内存中创建代理对象.
class JdkProxyFactory{
public static Object getInstance(Object target){
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
//代理对象调用触发invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--开启事务");
Object invoke = method.invoke(target, args);//去调用目标对象方法
System.out.println("--提交事务");
return invoke;//方法返回值
}
});
return proxy;//返回代理对象
}
}
class JdkProxyModeMain{
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
//动态的在内存中创建代理对象,代理对象和UserDaoImpl一样实现了UserDao接口,即是UserDao接口的实现类
UserDao proxy = (UserDao) JdkProxyFactory.getInstance(userDao);
proxy.save();
}
}
目标对象一定要实现接口,否则不能用JDK动态代理。
在内存中构建一个子类对象从而实现对目标对象功能的扩展.Cglib包的底层是通过使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类.
引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-xx.jar即可;
class AdminDao{
public void save(){
System.out.println("保存了数据...");
};
}
class CglibProxyFactory implements MethodInterceptor {
Object target;
public CglibProxyFactory(Object target) {
this.target = target;
}
//获取代理对象
public Object getInstance(){
Enhancer enhancer = new Enhancer();//1.工具类
enhancer.setSuperclass(target.getClass());//2.设置父类
enhancer.setCallback(this);//3.设置回调函数。将当前的工厂对象作为回调对象
Object obj = enhancer.create();//4.创建子类(代理对象)
return obj;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("--开启事务");
Object returnValue = method.invoke(target, objects);//去调用目标对象方法
System.out.println("--提交事务");
return returnValue;
}
}
class CglibProxyModeMain{
public static void main(String[] args) {
AdminDao adminDao = new AdminDao();
AdminDao proxy = (AdminDao) new CglibProxyFactory(adminDao).getInstance();
proxy.save();
}
}
在Spring的AOP编程中:
如果加入容器的目标对象有实现接口,用的JDK代理
如果目标对象没有实现接口,用的Cglib代理
模板模式主要由抽象模板(Abstract Template)角色和具体模板(Concrete Template)角色组成。
//抽象模板
abstract class OneDay{
public void getup(){
System.out.println("起床");
}
public void sleep(){
System.out.println("睡觉了...");
}
//具体模板执行流程
public void dayAll(){
getup();
goWork();
goHome();
sleep();
}
public abstract void goWork();
public abstract void goHome();
}
class Worker extends OneDay{
@Override
public void goWork() {
System.out.println("骑着小毛驴去上班");
}
@Override
public void goHome() {
System.out.println("骑着小毛驴回家");
}
}
class Boss extends OneDay{
@Override
public void goWork() {
System.out.println("开着大奔上班去");
}
@Override
public void goHome() {
System.out.println("开着大奔回家");
}
}
class TemplateMethodModeMain{
public static void main(String[] args) {
new Boss().dayAll();
new Worker().dayAll();
}
}
优点:模板方法所不变的行为搬到超类,去除子类中的重复代码,提供了一个很好了代码复用平台;子类不用关心具体执行流程和公共行为,只需实现要求你实现的方法即可。
缺点:当类的功能越来越多,变得复杂时,抽象类的管理和扩展就变得复杂了。
当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。
//被观察者通用接口
interface Observable {
void addObserver(Observer observer);//添加观察者
void removeObServer(Observer observer);//移除观察者
void notifyAllObserver();//通知所有观察者
}
class Weather implements Observable {
private List list = new ArrayList<>();
private double temperature;
public void setTemperature(double temperature) {
this.temperature = temperature;
}
@Override
public void addObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObServer(Observer observer) {
list.remove(observer);
}
@Override
public void notifyAllObserver() {
for (Observer observer : list) {
observer.update(temperature);
}
}
}
//观察者通用接口
interface Observer {
void update(double temperature);
}
class Person implements Observer{
@Override
public void update(double temperature) {
System.out.println("温度更新了,当前温度值:"+temperature+",快回家收衣服啊...");
}
}
class Dog implements Observer{
@Override
public void update(double temperature) {
System.out.println("温度更新了,当前温度值:"+temperature+",天气好热,找个大树乘凉去...");
}
}
class ObserverModeMain{
public static void main(String[] args) {
Weather weather = new Weather();
weather.addObserver(new Person());
weather.addObserver(new Dog());
weather.setTemperature(38D);
weather.notifyAllObserver();
}
}
Target(目标抽象类DC5Adapter):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adapter(适配器类ChinaDC5Adapter):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
Adaptee(适配者类AC220):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
class AC220{
private final int output = 220;
public int outputAC(){
return output;
}
}
//适配通用接口
interface DC5Adapter{
int outputDC5();
}
//中国的手机适配器
class ChinaDC5Adapter implements DC5Adapter{
private AC220 ac = new AC220();
@Override
public int outputDC5() {
int i = ac.outputAC();
System.out.println("适配前,电压:"+i);
int dc = i / 44;
System.out.println("适配后,电压为:"+dc);
return dc;
}
}
class AdapterModeMain{
public static void main(String[] args) {
//适配器对象
DC5Adapter dc5Adapter = new ChinaDC5Adapter();
int i = dc5Adapter.outputDC5();
}
}
环境类(Context):用来操作策略的上下文环境。
抽象策略类(Strategy):策略的抽象
具体策略类(ConcreteStrategy):具体的策略实现,每一种出行方式的具体实现。
//策略通用接口
interface Operation{
void execute(int i, int j);
}
//策略实现类
class Add implements Operation{
@Override
public void execute(int i, int j) {
int result = i+j;
System.out.println("加法结果:"+result);
}
}
class Sub implements Operation{
@Override
public void execute(int i, int j) {
int result = i -j;
System.out.println("减法结果:"+result);
}
}
//上下文环境类
class Context{
Operation operation;
public Context(Operation operation) {
this.operation = operation;
}
public void executeStrategy(int i, int j){
operation.execute(i, j);//调用的是实现类的具体实现
}
}
class StrategyModeMain{
public static void main(String[] args) {
int i=10,j=20;
new Context(new Add()).executeStrategy(i,j);
new Context(new Sub()).executeStrategy(i,j);
}
}
优点:策略实现类可灵活实现。缺点:策略实现类繁多且需要开发者全部了解,维护麻烦。
扩展对象的功能,是继承关系的一个替代。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。即扩展对象功能但不使用继承。
interface Animal{
void function();
}
class Cat implements Animal{
@Override
public void function() {
System.out.println("我会吃饭睡觉...");
}
}
class Decorator implements Animal{
Animal animal;//组合模式
public Decorator(Animal animal) {
this.animal = animal;
}
@Override
public void function() {
animal.function();//实际调用的是实现类方法
}
}
class CatDecorator extends Decorator{
public CatDecorator(Animal animal) {
super(animal);
}
@Override
public void function() {
super.function();
System.out.println("我还会抓老鼠...");
}
}
class DecoratorModeMain{
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println("装饰前:");
cat.function();
CatDecorator catDecorator = new CatDecorator(cat);
System.out.println("装饰后:");
catDecorator.function();
}
}