设计模式第七次作业——单例模式和享元模式

  • Post author:
  • Post category:其他




单例模式——读取配置文件到内存

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class main {
	public static void main(String[] args) {
		AppConfig config = new AppConfig();
		String paramA = config.getParameterA();
		String paramB = config.getParameterB();
		System.out.println("paramA=" + paramA + ",paramB=" + paramB);
	}
}

class AppConfig {
	private String parameterA;
	private String parameterB;

	public String getParameterA() {
		return parameterB;
	}

	public String getParameterB() {
		return parameterB;
	}

	public AppConfig() {
		readConfig();
	}

	private void readConfig() {
		Properties p = new Properties();
		InputStream in = null;
		try {
			in = AppConfig.class.getResourceAsStream("AppConfig.properties");
			p.load(in);// 获取资源文件的输入流,从输入流中读取属性列表
			this.parameterA = p.getProperty("paramA");
			this.parameterB = p.getProperty("paramB");
		} catch (IOException e) {
			System.out.println("装载配置文件出错");
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}



单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点

  • 单例模式的特点:
  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须给所有其他对象提供这一实例
public class main {
	public static void main(String[] args) {
		// Singleton s0=new Singleton();
		Singleton s1 = Singleton.GetInstance();
		Singleton s2 = Singleton.GetInstance();
		if (s1 == s2) {
			System.out.println("两个对象是相同的实例");

		} else {
			System.out.println("两个对象是不同的实例");
		}
	}
}

//单例类
class Singleton {
	private static Singleton instance;

	private Singleton() {
	}

	public static Singleton GetInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;

	}
}



多线程时的单例

public class main {
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		if (s1 == s2) {
			System.out.println("该对象的字符串表示形式:");
			System.out.println("singleton1:"+s1.toString());
			System.out.println("singleton2:"+s2.toString());
		}
	}
}

class Singleton {
	private static Singleton instance;
	private static final Object syncRoot = new Object();// 程序运行时创建一个静态只读的进程辅助对象

	public static Singleton getInstance() {
		synchronized (syncRoot) {//在同一时刻加了锁的部分程序只有一个线程可以进入
			if (instance == null) {
				instance = new Singleton();
			}
		}
		System.out.println("singleton创建");
		return instance;
	}
}
  • 这里不直接synchronized(instance),而是再创建一个syncRoot来synchronized的原因:
  • 在加锁时,instance不一定被创建过,无法对它加锁。



双重锁定: 不用让线程每次都加锁,而只是在实例未被创建的时候加锁。

public class main {
	public static void main(String[] args) {
		SingletonDCL s1=SingletonDCL.getInstance();
		SingletonDCL s2=SingletonDCL.getInstance();
		System.out.println("s1==s2?"+(s1==s2));
		System.out.println("该对象的字符串表示形式:");
		System.out.println("singleton1:"+s1.toString());
		System.out.println("singleton2:"+s2.toString());
	}
}
class SingletonDCL{
	private volatile static SingletonDCL singleton;
	private SingletonDCL() {}
	public static SingletonDCL getInstance() {//此方法是获得本类实例的唯一全局访问点
		if(singleton==null) {//给类加锁,类的所有对象用同一把锁
			synchronized(SingletonDCL.class) {
				if(singleton==null) {
					singleton=new SingletonDCL();
				}
			}
		}
		System.out.println("singleton创建");
		return singleton;
	}
}


单例模式的实现分为两种:



懒汉式单例模式(时间换空间)

:在第一次被引用时才会将自己实例化。

class Singleton {
	private static Singleton instance;

	private Singleton() {
	}

	public static Singleton GetInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}


饿汉式单例模式(空间换时间)

:只能在静态初始化期间或在类构造函数中分配变量,

这种静态初始化的方式是在自己被加载时就将自己实例化。

 class Singleton{
	private static Singleton instance=new Singleton();
	private Singleton(){}
	public static Singleton GetInstance() {
		return instance;
	}
}


二者主要区别:

  • 懒汉式会面临这多线程访问的安全性问题,需要做双重锁定处理才可以保证安全。

  • 饿汉式即静态初始化的方式,它是类一加载就实例化的对象,所以要提前占用系统资源。**



享元模式——实现不同客户对同一网站的不同需求



将对象的状态按照是否会变化分为不同的状态,共享不变的状态

//客户端代码
public class main {
	public static void main(String[] args) {
		WebSite fx=new WebSite("产品展示");
		fx.Use();
		WebSite fy=new WebSite("产品展示");
		fy.Use();
		WebSite fz=new WebSite("产品展示");
		fz.Use();
		WebSite fl=new WebSite("博客");
		fl.Use();
		WebSite fm=new WebSite("博客");
		fm.Use();
		WebSite fn=new WebSite("博客");
		fn.Use();
	}
}
//网站类
class WebSite{
	private String name="";
	public WebSite(String name) {
		this.name=name;
	}
	public void Use() {
		System.out.println("网站分类:"+name);
	}
}


上面的代码有资源浪费问题

解决方法:

利用用户的ID号来区分不同的用户,各个小网站的具体数据和模板乐意不同,但核心代码却是共享的。

public class main {
	public static void main(String[] args) {
		int extrinsic=22;
		FlyweightFactory f=new FlyweightFactory();
		Flyweight fx=f.getFlyweight("X");
		fx.operate(--extrinsic);
		Flyweight fy=f.getFlyweight("Y");
		fy.operate(--extrinsic);
		Flyweight fz=f.getFlyweight("Z");
		fz.operate(--extrinsic);
		Flyweight fex=f.getFlyweight("X");
		fex.operate(--extrinsic);
		Flyweight unsharedFlyweight=new UnsharedConcreteFlyweight("X");
		unsharedFlyweight.operate(--extrinsic);
	}
}


/*享元类是所有具体享元类的超类或接口,通过这个接口,享元类可以接受并作用域外部状态。*/
abstract class Flyweight{
	public String intrinsic;//内部状态
	protected final String extrinsic;//外部状态
	public Flyweight(String extrinsic) {
		this.extrinsic=extrinsic;
	}
	public abstract void operate(int intrinsic) ;//定义业务操作
	public String getIntrinsic() {
		return intrinsic;
	}
	public void setIntrinsic(String intrinsic){
		this.intrinsic=intrinsic;
	}
}
class ConcreteFlyweight extends Flyweight{
    public ConcreteFlyweight(String extrinsic) {
	super(extrinsic);
}
	public void operate(int extrinsic) {
		System.out.println("具体的Flyweight:"+extrinsic);
	}
}
class UnsharedConcreteFlyweight extends Flyweight{
	public UnsharedConcreteFlyweight(String extrinsic) {
		super(extrinsic);
	}
	public void operate(int extrinsic) {
		System.out.println("不共享的具体的Flyweight:"+extrinsic);
	}
}
//享元工厂
class FlyweightFactory{
	private static HashMap<String,Flyweight>pool=new HashMap<String,Flyweight>();
	public static Flyweight getFlyweight(String extrinsic) {
		Flyweight flyweight=null;
		if(pool.containsKey(extrinsic)) {//池中有对象
			flyweight=pool.get(extrinsic);
			System.out.print("创建"+extrinsic+"并从池中取出");
		}else {
			flyweight=new ConcreteFlyweight(extrinsic);
			pool.put(extrinsic, flyweight);//放入池中
			System.out.print("创建"+extrinsic+"并从池中取出");
		}
		return flyweight;
	}
}
public class main {
	public static void main(String[] args) {
		WebSiteFactory f=new WebSiteFactory();
		WebSite fx=f.GetWebSiteCategory("产品展示");
		fx.Use();
		WebSite fy=f.GetWebSiteCategory("产品展示");
		fy.Use();
		WebSite fz=f.GetWebSiteCategory("产品展示");
		fz.Use();
		WebSite fl=f.GetWebSiteCategory("博客");
		fl.Use();
		WebSite fm=f.GetWebSiteCategory("博客");
		fm.Use();
		WebSite fn=f.GetWebSiteCategory("博客");
		fn.Use();
	}
}
abstract class WebSite{
	public abstract void Use();
}
class ConcreteWebSite extends WebSite{
	private String name="";
	public ConcreteWebSite(String name) {
		this.name=name;
	}
	
	public void Use() {
		System.out.println("网站分类:"+name);
	}
}
//网站工厂
class WebSiteFactory{
	private static HashMap<String,WebSite>flyweights=new HashMap<String,WebSite>();//获得网站分类
	public WebSite GetWebSiteCategory(String key) {
		if(!flyweights.containsKey(key)) {
			WebSite flyweight=new ConcreteWebSite(key);
			flyweights.put(key, flyweight);
		}
		return (flyweights.get(key));
	}
	public int GetWebSiteCount() {//获得网站分类总数
		return flyweights.size();
	}
}
public class main {
	public static void main(String[] args) {
		WebSiteFactory f=new WebSiteFactory();
		WebSite fx=f.GetWebSiteCategory("产品展示");
		fx.Use(new User("小草"));
		WebSite fy=f.GetWebSiteCategory("产品展示");
		fy.Use(new User("大鸟"));
		WebSite fz=f.GetWebSiteCategory("产品展示");
		fz.Use(new User("小花"));
		
	}
}
//网站抽象类
abstract class WebSite{
	public abstract void Use(User user);
}
class User{
	private String name;
	User(String name){
		this.name=name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name=name;
	}
}
class ConcreteWebSite extends WebSite{
	private String name="";
	public ConcreteWebSite(String name) {
		this.name=name;
	}

	public void Use(User user) {
		System.out.println("网站分类:"+name+"用户:"+user.getName());
		
	}
}

class WebSiteFactory{
	private static HashMap<String,WebSite>flyweights=new HashMap<String,WebSite>();//获得网站分类
	public WebSite GetWebSiteCategory(String key) {
		if(!flyweights.containsKey(key)) {
			WebSite flyweight=new ConcreteWebSite(key);
			flyweights.put(key, flyweight);
		}
		return (flyweights.get(key));
	}
	public int GetWebSiteCount() {//获得网站分类总数
		return flyweights.size();
	}
}



版权声明:本文为weixin_43470016原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。