工厂
工厂模式主要是为了解耦,A类想要调用B类,但是实例化B对象比较复杂,所以我们就把B对象的创建放到工厂里面统一管理。由于B对象的创建已经统一了起来,所以即使业务逻辑发生变化,我们也只需要修改工厂类,而不需要寻找每个创建B对象的地方去修改。
例如,我们项目可能会使用多个数据库源,但是他们的JDBC配置是不同的,所以我们就可以使用工厂模式来统一,也减少了使用者出错的概率。
使用场景:
精确数据计算,获取Jdbc连接,或者类似的通讯连接
实现:
简单工厂:
首先创建一个接口
public interface Operation {
public double getResult(double numberA,double numberB) throws Exception;
}
然后是加减乘除的实现类
public class Add implements Operation{
// 加法计算
public double getResult(double numberA, double numberB) {
return numberA + numberB;
}
}
// 减 Sub
// 乘 Mul
// 除 Div
然后是简单工厂
public class EasyFactory {
// 简单工厂,根据字符串创建相应的对象
public static Operation createOperation(String name) {
Operation operationObj = null;
switch (name) {
case "+":
operationObj = new Add();
break;
case "-":
operationObj = new Sub();
break;
case "*":
operationObj = new Mul();
break;
case "/":
operationObj = new Div();
break;
}
return operationObj;
}
}
调用:
public class Client {
public static void main(String[] args) throws Exception {
Operation add = EasyFactory.createOperation("+");
Operation sub = EasyFactory.createOperation("-");
Operation mul = EasyFactory.createOperation("*");
Operation div = EasyFactory.createOperation("/");
System.out.println(add.getResult(1, 1));
System.out.println(sub.getResult(1, 1));
System.out.println(mul.getResult(1, 1));
System.out.println(div.getResult(1, 1));
}
}
工厂模式
工厂方法模式是对简单工厂模式进一步的解耦,因为在工厂方法模式中是一个子类对应一个工厂类,而这些工厂类都实现于一个抽象接口。这相当于是把原本会因为业务代码而庞大的简单工厂类,拆分成了一个个的工厂类,这样代码就不会都耦合在同一个类里了。
实现:
首先定义工厂接口:
import com.ljy.Mode.Operation;
public interface Factory {
public Operation createOperation() ;
}
然后是工厂实现类
// 加法类工厂
public class AddFactory implements Factory{
public Operation createOperation() {
System.out.println("加法运算");
return new Add();
}
}
// 减法类工厂
public class SubFactory implements Factory{
public Operation createOperation() {
System.out.println("减法运算");
return new Sub();
}
}
........
调用:
public class Client {
public static void main(String[] args) throws Exception {
// 使用反射机制实例化工厂对象,因为字符串是可以通过变量改变的
Factory addFactory = (Factory) Class.forName("com.ljy.mode.factory.AddFactory").newInstance();
Factory subFactory=(Factory) Class.forName("com.ljy.mode.factory.SubFactory").newInstance();
// 通过工厂对象创建相应的实例对象
Operation add = addFactory.createOperation();
Operation sub = subFactory.createOperation();
System.out.println(add.getResult(1, 1));
System.out.println(sub.getResult(1, 1));
}
}
抽象工厂模式
抽象工厂与工厂方法模式的区别在于:抽象工厂是可以生产多个产品的,它围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
说白了,就是创建一个抽象工厂,然后建立其他工厂类实现。
实现就不写了 有点麻烦,以后补充。
单例
单例设计模式,就是有一个准则,那就是只有一个对象被创建!!!,而且单例也是最简单的设计模式了
单例模式的作用很明显,首先,节省内存,因为我只有一个对象,其次,我能保证数据的唯一性。
为了保证对象唯一性,所以我们首先要确定构造方法的私有性,这样的话就不能通过new的方式创建对象了,然后我们可以在内部创建自身对象,但是对象必须是私有的,然后,我们需要一个静态的公开的方法,来让外部类获取对象。
饿汉模式
饿汉,一直在叫着“我好饿啊”,啥都想吃,所以,这种设计模式,是在一开始就已经把对象创建好了,但是,会造成内存浪费啊,就算没用到他,也会在哪里占着浪费内存。
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
懒汉模式
懒汉啥样的,那当然是懒啊,所以懒汉模式,就意味着,只有等到需要这个对象的时候,才回去创建对象
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
但是这种设计模式,有个很大的缺点,那就是线程不安全!!!一旦多个线程同时进来,那就会创建多个对象,违反我们的原则了。
那要是线程不安全咋办呢,简单啊,那就加锁呗。
饿汉模式(同步方法)
public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static synchronized Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
但是加锁一时爽,效率太差了啊,那么多线程都在方法外面等着呢啊
饿汉模式(双重检查)
既然加锁方法会造成效率低下,那咱们就把加锁的位置改一下吧,放在方法里面
public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static synchronized Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
但是,一想想,不对啊 这样还是会造成线程不安全啊,导致出现两个对象啊,不行不行,那咋办呢 要不再加个锁?可是锁加在哪里呢?
饿汉模式(双重锁)
于是,我们就加了个锁,将这个锁加载了声明对象的时候,使用了volatile,这个版本也是非常完美的版本的,面试推荐哦
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;
}
}
那么我们总想着懒汉饿汉,是不是还有其他方式呢(注意,上面任意一种方式,都是无法阻止反射的!!!或者通过序列化 ,我们也是可以获得两个对象),其实是有的,那就是枚举,枚举是天生的单例,而且可以阻止反射哦
枚举
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
看,是不是,非常简单,代码量也很少
装饰器
装饰器模式的定义是允许向一个现有的对象添加新的功能,同时又不改变其结构。就像是,我下个单,中间可能会有打折,可能会有运费,价格就会变动,所以我们就可以通过装饰器模式来实现。
至于实现的话,其实也是主要靠继承与子类重写父类方法的原理来实现
首先一个接口是肯定的了:
public interface Component {
public void biu();
}
然后接口实现类:
public class ConcretComponent implements Component {
public void biu() {
System.out.println("biubiubiu");
}
}
接下来是装饰器的接口:
//装饰类
public class Decorator implements Component {
public Component component;
public Decorator(Component component) {
this.component = component;
}
public void biu() {
this.component.biu();
}
}
最后就是装饰器接口实现类:
//具体装饰类
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void biu() {
System.out.println("fire in the hole");
this.component.biu();
}
}
说白了是不是感觉很简单的,不就是多态么。
具体调用是这样的:
public class Client {
public static void main(String[] args) {
//使用装饰器
Component component = new ConcreteDecorator(new ConcretComponent());
component.biu();
}
}
代理
代理,一说起代理我们就可以联想到代理商,代理商干嘛的,那不就是帮助别人做事的么,例如什么猎头啊,中介啊,类似的,都是代理的体现。而且我们还可以借助代理类再次增加一些功能,而不需要修改原有代码。符合开闭原则。
至于到项目开发中,我们总会遇见一些事情,是我们不想让我们的实现类实现的,例如,日志啊,缓存啊,我们想在这个实现类执行的前后执行另外的一些操作,这就用到了我们的代理模式了。
同时代理模式和装饰器模式是不一样的!!!。
装饰器模式和代理模式的区别:
装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
代理分为静态代理和动态代理。
静态代理
静态代理是在运行前,代理类的class文件就已经创建好了。但是呢,静态代理也有缺点,我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
首先是接口:
package com.ljy.util.designMode.proxy;
public interface BuyHouse {
void buyHosue();
}
然后是实现类:
package com.ljy.util.designMode.proxy;
public class BuyHouseImpl implements BuyHouse {
@Override
public void buyHosue() {
System.out.println("我要买房");
}
}
然后就是静态代理类:
package com.ljy.util.designMode.proxy;
public class BuyHouseProxy implements BuyHouse {
private BuyHouse buyHouse;
public BuyHouseProxy(final BuyHouse buyHouse) {
this.buyHouse = buyHouse;
}
@Override
public void buyHosue() {
System.out.println("买房前准备");
buyHouse.buyHosue();
System.out.println("买房后装修");
}
}
最后是测试类:
package com.ljy.util.designMode.proxy;
public class ProxyTest {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImpl();
buyHouse.buyHosue();
BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
buyHouseProxy.buyHosue();
}
}
动态代理
动态代理是在程序运行时通过反射机制动态创建的。
在动态代理中我们不再需要再手动的创建代理类,我们只需要编写一个动态处理器就可以了。真正的代理对象由JDK再运行时为我们动态的来创建。
首先让我们创建动态代理类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* JDKDynamicProxy
* jdkd动态代理
*
* @author
* @create 2018-03-29 16:17
**/
public class JDKDynamicProxy implements InvocationHandler { // 一定要实现这个类哦
private Object target;
public JDKDynamicProxy(Object target) {
this.target = target;
}
/**
* 获取被代理接口实例对象
* @param <T>
* @return
*/
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("买房前准备");
Object result = method.invoke(target, args);
System.out.println("买房后准备");
return result;
}
}
然后就是测试类:
package com.ljy.util.designMode.proxy.dynamic;
import com.ljy.util.designMode.proxy.BuyHouse;
import com.ljy.util.designMode.proxy.BuyHouseImpl;
/**
* Client
* client测试代码
**/
public class Client {
public static void main(String[] args) {
// 将JDK动态代理生成的class文件保存到本地
// System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true"); // 或者是这个
// jdk动态代理测试
BuyHouse buyHouse = new JDKDynamicProxy(new BuyHouseImpl()).getProxy();
buyHouse.buyHosue();
}
}
是不是,只需要一个动态代理类就可以实现了,还不需要针对每个实现类开发。
未完待续。。。