设计模式
1.单例模式
单例模式:为了解决同一对象要创建很多次的问题。因为同一个对象只创建一次,为了节约内存空间。比如很多用户浏览同一商品,当点击同一商品的信息时,其实创建相同的对象.
我们可以通过地址是否相等来判断对象实例化(new)了几次。
本次单例模式学习到的有三种:
- 懒汉式
- 饿汉式
- 枚举
一般情况下使用的是饿汉式,但是枚举是实现单例模式的最佳方法。
注意最好让构造器和实例对象为私有的。
懒汉式:
懒汉式没那么“饿”,只有在真正需要的时候再去创建实例。所以在类中先判断实例是否为空,为空再去创建。但是在多线程中会出问题,因为可能同时创建多个实例。
public class OneDemo {
public static void main(String[] args) {
//先不用单例模式
One o1=new One();
One o2=new One();
//如果o1和o2地址不同,说明创建了两个对象
System.out.println(o1==o2); //false 说明没有单例模式钱创建2个对象
//单例模式
One o3=One.getdanli();
One o4=One.getdanli();
System.out.println(o3==o4); //true
}
}
//一般类
class One{
//使用单例模式:
/*
//因为static只有一份,后面可判断o变量
// 有没有来鉴定One对象有没有被创建
*/
private One(){}
private volatile static One o=null; //重点
public static One getdanli(){
if (o==null){ //重点
o=new One();
}
return o;
//改为线程安全的
if(o==null){
synchronized (One.class){
if(o==null){
o=new One();
}
}
}
}
}
上面是一个双重校验锁实现对象实例
此外需要注意 o 采⽤ volatile 关键字修饰也是很有必要。
o 采⽤ volatile 关键字修饰也是很有必要的, o = new One();
这段代码其实是分为三步执⾏:
- 为 o 分配内存空间
- 初始化 o
- 将 o 指向分配的内存地址
但是由于 JVM 具有指令重排的特性,执⾏顺序有可能变成 1i>3i>2。指令重排在单线程环境下不会出
现问题,但是在多线程环境下会导致⼀个线程获得还没有初始化的实例。例如,线程 T1 执⾏了 1 和
3,此时 T2 调⽤ getdanli() 后发现 o 不为空,因此返回
uniqueInstance,但此时 o 还未被初始化。
使⽤ volatile 可以禁⽌ JVM 的指令重排,保证在多线程环境下也能正常运⾏。
饿汉式:
饿汉式太饿啦~在类加载的时候就已经把类的实例创建出来了!
//单例模式
public class OneDemo {
public static void main(String[] args) {
hungerone ho1=hungerone.getHo();
hungerone ho2=hungerone.getHo();
System.out.println(ho1==ho2); //true
}
}
class hungerone{
private static hungerone ho=new hungerone(); //重点
private hungerone(){}
public static hungerone getHo(){
return ho;
}
}
枚举:
利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题。自动支持序列化机制,绝对防止多次实例化。
public class OneDemo {
public static void main(String[] args) {
enumone.INSTANCE.wh();
}
}
enum enumone{
INSTANCE;
public void wh(){ }
}
2.工厂模式:
工厂模式:按照传入的参数,实例化(new)出相应的对象。有一个工厂类或方法,专门负责按照参数,生成相应的对象。把整个创建对象的过程,封装好。达到的效果是我们创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
下面的代码,我们在getper方法中根据我们传入的不同值new不同的类,达到一个封装的效果,我们只需要传入数字,不需要知道具体的类名。
//工厂模式
public class FactDemo {
public static void main(String[] args) {
//没使用设计模式
person p1=new Stu();
person p2=new Tea();
p1.eat();
p2.eat();
//调用设计模式
FactDemo f=new FactDemo();
person p3=f.getper(1);
person p4=f.getper(0);
p3.eat();
p4.eat();
}
//定义一个方法,创建对象
public person getper(int i){
if (i==0){
return new Stu();
}else if (i==1){
return new Tea();
}else {
return null;
}
}
}
//接口,因为要使用多态来开发 人
interface person{
void eat();
}
//
class Stu implements person{
@Override
public void eat() {
System.out.println("学生在食堂吃饭");
}
}
class Tea implements person{
@Override
public void eat() {
System.out.println("老师在教师食堂吃饭");
}
}
3.代理模式:
代理模式:我们使用一个类代表另一个类的功能。通过第三方(代理方),去创建所须要的对象。
例子是 :
婚介中心:
男方: 找女友. 标准 会唱歌,会敲代码
中介: 完成男方的要求,调用女方。–代理方
女方: 小芳 小丽 满足上面的条件.
本例子我们通过中介来代理女方类的功能。
缺点:
①:代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展
②:每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。
解决方法:动态代理
public class homework {
public static void main(String[] args) throws ParseException {
proxy p1=new agency("yzl");
proxy p2=new agency("zzp");
p1.proxyperson();
p2.proxyperson();
}
}
interface proxy{
void proxyperson();
void proxypersontel();
}
class yzl implements proxy{
@Override
public void proxyperson() {
System.out.println("代理人:yzl");
}
@Override
public void proxypersontel() {
System.out.println("代理人电话:111111");
}
}
class zzp implements proxy{
@Override
public void proxyperson() {
System.out.println("代理人:zzp");
}
@Override
public void proxypersontel() {
System.out.println("代理人电话:222222");
}
}
//代理类 重点
class agency implements proxy{
proxy p;
public agency(String i){
if (i.equals("yzl")){
p=new yzl();
}else if (i.equals("zzp")){
p=new zzp();
}else {
p=null;
}
}
@Override
public void proxyperson() {
p.proxyperson();
}
@Override
public void proxypersontel() {
p.proxypersontel();
}
}
我们通过agency这个代理类来实现了代理模式
4.代理工厂模式:
建立在代理模式之上,针对多个类型,由工厂模式封装创建过程。通过代理得到各种类型对象的创建。
用这个模式是因为代理模式有个缺点:
上面的类在里面实例化后通过构造器,分配赋给不同的实例对象,但是可能会面临属性不够用的问题,可能还会有其他的要求,这时候我们就需要采用代理工厂模式。
例如:
车:
发动机厂商
空调厂商
外形厂商
…
选一辆车,得到三个类型,并这个类型都有可能是父类,下面分别还有很多子类。
下面的具体汽车的品牌就是代理类,在里面实现了对不同对象的实例化。
代码如下:
public class ProFactoryDemo {
public static void main(String[] args) {
BZpri b=new BZpri();
b.createAir(0);
b.createEn(1);
BWMpri b2=new BWMpri();
b2.createAir(1);
b2.createEn(0);
}
}
//发动机的父类
class Engine{
int id;
int hi;
}
//发动机厂商的子类
class FT extends Engine{
public FT(){
System.out.println("我是丰田的发动机");
}
}
class DZ extends Engine{
public DZ(){
System.out.println("我是大众的发动机");
}
}
//空调父类
class Air{
String type;
int pi;
}
//空调子类
class MD extends Air{
public MD(){
System.out.println("美的制造的空调");
}
}
class GL extends Air{
public GL(){
System.out.println("格力制造的空调");
}
}
//抽象工厂
interface Abstract{
Engine createEn(int i);
Air createAir(int i);
}
//代理类
class BZpri implements Abstract{
Engine e;
Air a;
@Override
public Engine createEn(int i) {
if (i==0){
e=new DZ();
}else{
e=new FT();
}
return e;
}
@Override
public Air createAir(int i) {
if (i==0){
a=new MD();
}else{
a=new GL();
}
return a;
}
}
class BWMpri implements Abstract{
Engine e;
Air a;
@Override
public Engine createEn(int i) {
if (i==0){
e=new DZ();
}else{
e=new FT();
}
return e;
}
@Override
public Air createAir(int i) {
if (i==0){
a=new MD();
}else{
a=new GL();
}
return a;
}
}