本篇文章用来写学习中遇到的java设计模式
1. 模板方法设计模式
在定义功能时,功能的一部分是确定的,但有一部分是不确定的,而确定的部分在使用不确定的部分,此时就将不确定的部分暴露出去,由该类的子类去完成。也就是说为了避免子类的重复代码,我们将那些可能实现不同的细节暴露出去,由子类进行重写。
例如: 需求是 获取一个程序运行的时间 。
分析: 我们可以获取程序开始和结束的时间,相减即可。
package test;
abstract class GetTime{
public final void getTime(){
long start = System.currentTimeMillis();
//具体的功能由子类实现
runcode();
long end = System.currentTimeMillis();
System.out.println("毫秒:"+(end-start));
}
public abstract void runcode();
}
// 实现具体的功能
class SubTime extends GetTime{
public void runcode(){
for(int x=0; x<4000; x++){}
}
}
public class TemplateDemo{
public static void main(String[] args) {
SubTime gt = new SubTime();
gt.getTime();
}
}
总结: 即提取出公用的代码,而将那些可变的行为交由子类去实现。
2. 单例模式
保证一个类只有一个实例,设计一个公共的方法,返回该实例。
常见的单例实现模式有 饿汉式,懒汉式。
饿汉式举例如下
package test;
/**
* 单例模式之----饿汉式,
* 在类加载时就进行了初始化。
*
*/
public class SingleDemo {
private static final SingleDemo singleDemo =new SingleDemo();
private SingleDemo() {}
public static SingleDemo getInstance(){
return singleDemo ;
}
}
上述实现模式的问题在于 单例产生的时机无法控制,假如该实例中存在一个静态变量,那么当访问该静态变量时,就会触发创建类的实例。对其改造如下:懒汉模式
懒汉式举例如下:
package test;
/**
* 懒汉式
* 类加载时并没有初始化。延迟加载
*/
public class SingleDemo2 {
// 将构造方法私有化,禁止通过new进行创建
private SingleDemo2() {}
private static SingleDemo2 singledemo2 = null;
// 使用的时候才开始初始化该对象
public static synchronized SingleDemo2 getInstance(){
if(singledemo2 ==null)
singledemo2=new SingleDemo2() ;
return singledemo2 ;
}
}
上述实现模式同样存在问题,虽然在同步方法中并没有做什么耗时的操作,但是在高并发中,多个线程进入时仍需要判断锁,所以也存在性能问题。对于改造如下:
public class StaticSingleton{
private StaticSingleton(){
System.out.println("Singleton is create");
}
private static class SingleHolder{
private static StaticSingletoninstance=new StaticSingleton();
}
public static StaticSingleton getInstance(){
return SingleHolder.instance ;
}
}
当 StaticSingleton被初始化的时候,其内部的静态内部类是不会被初始化的,只有当访问到 getInstance时,才会触发内部类的初始化。
3. 装饰设计模式
当对一组对象自的功能进行增强时,就可以使用该模式进行问题的解决。
和继承一样,都能进行功能的扩展。
假如有一个继承体系:
Writer
1-- TextWriter : 用于操作文本
1 -- MediaWriter : 用于操作媒体
如果想加入缓冲技术来提高效率,那么理论上我们可以通过继承来进行具体的功能的扩展。于是现有体系就变成:
Writer
1 -- TextWriter
1-- BufferedTextWriter :加入了缓冲技术的操作文本对象。
1 -- MediaWriter
1 -- BufferedMediaWriter :加入了缓冲技术的操作媒体对象。
慢慢的,以后随着功能的扩展,就会发现只为提高功能,而进行的继承,导致继承体系越来越臃肿,不够灵活。
重新思考下:
既然加入的是同一种技术,可不可以将缓冲技术进行单独的封装,哪个对象需要缓冲,就将哪个对象和缓冲关联。
eg:
class BufferWriter{
BufferWriter(Writer w)
{
直接对父类进行操作后,子类也跟着变化了 。
}
}
于是,现在继承体系就变为:
Writer
1--TextWriter :用于操作文本。
1--MediaWriter:用于操作媒体。
1--BufferWriter:用于提高效率。
装饰比继承更为灵活, 但是需要 装饰类和被装饰类都必须所属同一个接口或父类。
4. 不变模式
一个类的内部状态创建后,在整个生命周期间都不会发生改变时,就是不变类
不变模式时不需要同步的,并且不变模式不会被修改,即 仅仅是一个可读对象,并不需要同步,这样就提供了很高的性能。
public final class Product{
// 确保无子类
private final String no ;
// 私有属性,不会被其他对象获取。
private final String name ;
// final 保证属性不会被2次赋值
//final 修饰变量的时候,可以先声明,而不给初值,这被称为final空白,无论什么情况下,编译器都确保空白final在使用之前必须被初始化
private final double price ;
public Product(String no,String name,double price){// 在创建对象时,必须指定数据
super();
//因为创建之后,无法进行修改。
this.no =no ;
this.name=name ;
this.price=price ;
}
// getter ,注意:不需要setter
}
5. 生产者消费者模式
生产者消费者是一个经典的多线程设计模式。它为多线程的协作提供了良好的解决方案。在生产者-消费者模式中,通常有两类线程, 即若干个生产者线程和若干个消费者线程。生产者负责提交用户请求,消费者线程则负责具体处理生产者的提交的任务。生产者和消费者之间则通过共享内存缓冲区进行通信。 其实现见 Java多线程-生产者消费者问题
java多线程
6. 代理模式
代理模式就是说,给某个对象提供一个代理对象,由代理对象来控制原有对象自的行为,就如我们自己买票,由于抽不出空,所以提供信息给 售票贩子,让他们帮忙买。
代理模式主要有两种,jdk代理和cglib代理,两种代理模式在实现上稍有不同。
jdk代理 即实现 java.lang.reflect.InvocationHandler ,通过重写 invoke 即可。
public interface Person {
// 寻找真爱
void findLove();
String getName();
String getSex();
}
// ......
public class PersonProxy implements InvocationHandler {
private Person target;
// 获取代理人的 信息
public Object getInstance(Person target) throws Exception {
this.target = target;
Class clazz =target.getClass() ;
return Proxy.newProxyInstance(clazz.getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------ 代理类-------");
this.target.findLove();
return null;
}
}
public class XiaoXingxing implements Person {
private String sex = "女";
private String name = "小星星";
@Override
public void findLove() {
System.out.println("我叫: " +this.name +", 性别: " +this.sex+", 我的要求是:\n");
System.out.println("长得帅的");
System.out.println("有房有车的");
System.out.println("身高180cm以上,体重60kg");
}
// ........ 省略其他方法
}
// .....
public class TestFindLove {
public static void main(String[] args) {
// new XiaoXingxing().findLove();
try {
Person proxy= (Person)new PersonProxy ().getInstance(new XiaoXingxing());
proxy.findLove();
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
cglib代理如下:
public class YProxy implements MethodInterceptor {
public Object getInstance(Object obj) throws Exception{
Enhancer enhancer=new Enhancer();
//把父类设置为谁
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
//通过反射机制,给它实例化
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理模式" );
methodProxy.invokeSuper(o,objects);
return null;
}
}
// ........
public class YunZJ {
public void findLove(){
System.out.println("肤白貌美大长腿");
}
}
// ....
public class TestCglibProxy {
public static void main(String[] args) {
try {
YunZJ obj = (YunZJ)new YProxy().getInstance(new YunZJ());
obj.findLove();
}catch ( Exception e ){}
}
}
7. 工厂模式
该模式旨在隐藏复杂的逻辑过程,只关心结果。主要有简单工厂、工厂方法、抽象工厂。
简单工厂如下:
// 规定一定的标准
public interface Car {
// 规定汽车的品牌
String getName() ;
}
// ...
public class Benz implements Car {
@Override
public String getName() {
return "奔驰";
}
}
public class BMW implements Car {
@Override
public String getName() {
return "宝马";
}
}
public class SimpleFactory {
// 实现统一管理,专业化管理,通过不同条件(品牌),返回对应的汽车
public Car getCar(String name) {
if ("BMW".equalsIgnoreCase(name)) {
return new BMW();
} else if ("BENZ".equalsIgnoreCase(name)) {
return new Benz();
} else {
System.out.println("未有生产工艺");
return null;
}
}
}
// 对于消费者而言,并不需要关心其中的细节,只关心返回的结果。
public class SimpleFactoryTest {
public static void main(String[] args) {
// 消费者
Car car = new SimpleFactory().getCar("BMW");
System.out.println(car.getName());
}
}
工厂方法:
public interface Factory {
Car getCar();
}
//... 直接由对应的工厂生产出产品
public class BenzFactory implements Factory {
@Override
public Car getCar() {
return new Benz();
}
}
//***
public class BmwFactory implements Factory {
@Override
public Car getCar() {
return new BMW();
}
}
//***
public class FactoryTest {
public static void main(String[] args) {
// 工厂方法模式
//各个产品的生产商,都拥有各自的工厂,生产工艺,生成的高科技程度都是不一样的
Factory factory = new BenzFactory();
System.out.println(factory.getCar().getName());
factory = new BmwFactory();
System.out.println(factory.getCar().getName());
}
}
抽象工厂:
public abstract class AbstractFactory {
abstract Car getCar();
public Car getCar(String name) {
if ("BMW".equalsIgnoreCase(name)) {
return new BmwFactory().getCar();
} else if ("BENZ".equalsIgnoreCase(name)) {
return new BenzFactory().getCar();
} else {
System.out.println("未有生产工艺");
return null;
}
}
}
//***
public class BenzFactory extends AbstractFactory {
@Override
public Car getCar() {
return new Benz();
}
}
//***
public class BmwFactory extends AbstractFactory {
@Override
public Car getCar() {
return new BaoMa();
}
}
//***
public class DefaultFactory extends AbstractFactory {
private BenzFactory defaultFactory = new BenzFactory();
@Override
public Car getCar() {
return defaultFactory.getCar();
}
}
//***
public class AbstractFactoryTest {
public static void main(String[] args) {
DefaultFactory factory = new DefaultFactory();
System.out.println(factory.getCar().getName());
// factory=new DefaultFactory().ge;
System.out.println(factory.getCar("BMW").getName());
}
}
未完待续