JAVA 几种常见的设计模式

一、单例模式

单例设计模式简单说就是无论程序如何运行,采用单例设计模式的类永远只会有一个实例化对象产生。常见方法是将采用单例设计模式的类的构造方法私有化,并在其内部产生该类的实例化对象,并将其封装成private static类型,时定义一个静态方法返回该类的实例。

根据实例对象按需产生或是加载类时就产生可分为懒汉式和饿汉式

饿汉式:

public class SingleDemo {
	private SingleDemo(){}
	private static SingleDemo s=new SingleDemo();
	public static SingleDemo getInstance(){
		return s;
	}
}

懒汉式:两种方案

方案一

public class SingleDemo2 {

	private SingleDemo2(){};
	private static SingleDemo2 s=null;
	public SingleDemo2 getInstance(){
		if(s==null){
			synchronized (SingleDemo2.class) {
				if(s==null){
					s=new SingleDemo2();
				}
			}
		}
		return s;
	}
}
方案二

class Single1 {
	private Single1() {
	}

	// 定义私有的内部静态类 对外隐藏 ,外部类加载时内部类不会同时加载
	private static class SingleUtil {
		static Single1 single_new = new Single1();
	}

	public static Single1 getInstance() {
		// 此时有调用到内部类的静态方法,加载,实现了延迟加载的目的,同时类加载只加载一次,因此线程安全
		return SingleUtil.single_new;
	}
}

二、模板模式

模板模式中父类为抽象类,其中制定一个涵盖了实现逻辑的方法,并将部分逻辑以具体方法的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。
不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。
先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
我的理解是父类方法向子类指明了实现一个方法的具体步骤,其中某个步骤可以由父类指明具体实现,有些步骤则必须有子类亲自去具体实现.

下面是一个模板模式的例子

public abstract class Produce {

	protected void make() {

		proNum();// 获取商品编号
		System.out.println("生产一产品主体");
		color();// 定制颜色
		pack();// 包装
	}

	protected abstract void proNum();

	protected abstract void color();

	protected abstract void pack();

}

class MyProduce extends Produce{

	@Override
	protected void proNum() {
		// TODO Auto-generated method stub
		System.out.println("赋予商品编号"+System.currentTimeMillis());
	}

	@Override
	protected void color() {
		// TODO Auto-generated method stub
		System.out.println("赋予商品红色");
	}

	@Override
	protected void pack() {
		// TODO Auto-generated method stub
		System.out.println("将产品使用环保纸盒包装");
	}
	
}
测试:

public class BlogTest {
	public static void main(String[] args) {
		MyProduce produce=new MyProduce();
		produce.make();
	}
}


三、装饰模式

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。

如:自定义字符输入流的包装类,通过这个包装类对底层字符输入流进行包装,让程序通过这个包装类读取某个文本文件(时,能够在读取的每行前面都加上有行号和冒号。

这时需要自定义一个MyFileReader,并传入一个FileReader类,生成自己想要的新功能新方法。

public class BlogTest{
	public static void main(String[] args) throws Exception {
		MyFileReader in = new MyFileReader(new FileReader(new File(
				"D:\\test4.txt")));
		String line;
		while ((line = in.readLine()) != null) {
			System.out.print(line);
		}
	}
}

class MyFileReader {
	private FileReader reader;
	private int lineNum;

	public int getLineNum() {
		return lineNum;
	}

	public void setLineNum(int lineNum) {
		this.lineNum = lineNum;
	}

	public MyFileReader(FileReader reader) {
		this.reader = reader;
	}

	private MyFileReader() {

	}

	public String readLine() throws Exception {
		lineNum++;
		StringBuffer buf = new StringBuffer();
		// buf.append(lineNum+":");
		int data = 0;

		while ((data = reader.read()) != -1) {
			if ('\n' == data)
				break;
			buf.append((char) data);
		}
		if (buf.length() == 0)
			return null;
		return lineNum + ":\t" + new String(buf.toString().getBytes("UTF-8"), "UTF-8");

	}
}

四、工厂模式

1.简单工厂模式(结合反射)


public abstract class Electronics {
	abstract void run();
}
public class PC extends Electronics {

	@Override
	void run() {
		// TODO Auto-generated method stub
		System.out.println("PC---Eclipse");
	}

}
public class Phone extends Electronics {

	@Override
	void run() {
		// TODO Auto-generated method stub
		System.out.println("phone---打电话");
	}

}
下面是一个工厂类,根据传入的ClassName反射生成一个实例

public class Factory {
	public static Object getInstance(String className) throws Exception{
		Class clazz=Class.forName(className);
		return clazz.newInstance();
	}
}
测试

public class MyTest {
	public static void main(String[] args) throws Exception {
		Electronics phone = (Electronics) Factory.getInstance(Phone.class.getName());
		phone.run();
		Electronics pc = (Electronics) Factory.getInstance(PC.class.getName());
		pc.run();
	}
}
结果:

phone---打电话
PC---Eclipse

2.工厂方法模式

interface Factory {
	public abstract Electronics getInstance();
}

class PhoneFactory implements Factory {

	@Override
	public Electronics getInstance() {
		// TODO Auto-generated method stub
		return new Phone();
	}

}

class PCFactory implements Factory {

	@Override
	public Electronics getInstance() {
		// TODO Auto-generated method stub
		return new PC();
	}

}
用户需要不同设备只需调用不同工厂

public class MyTest {
	public static void main(String[] args) throws Exception {
		Factory phoneFactory = new PhoneFactory();
		Electronics phone = phoneFactory.getInstance();
		Factory pcFactory = new PCFactory();
		Electronics pc = pcFactory.getInstance();
		phone.run();
		pc.run();
	}
}
3.抽象工厂模式

前面两种工厂模式在实际使用中较少,而抽象工厂模式在开发中最为常见,可以配合配置文件切换数据库等等。

如下面的例子,有Iphone和Galaxy实现Phone接口,MacBook和Laptop实现PC接口,AppleFactory和SamsungFactory继承Factory抽象类,AppleFactor只生产Iphone和MacBook,SamsungFactory只生产Galaxy和LapTop。现在要实现不改变程序代码的情况下,只对配置文件做修改达到切换工厂,以改变生产的产品的目的。

interface PC{
	void run();
}
interface Phone{
	void run();
}
public class Iphone implements Phone {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("Iphone running....");
	}

}
public class Galaxy implements Phone {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("三星Galaxy手机 running...");
	}

}
public class LapTop implements PC{

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("三星 PC running...");
	}

}
public class MacBook implements PC {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("MacBook running...");
	}
	
}
下面是工厂类:

public abstract class Factory {
	abstract PC getPC();

	abstract Phone getPhone();

	static void getFactory() {

	};
}

class AppleFactory extends Factory {

	@Override
	public PC getPC() {
		// TODO Auto-generated method stub
		return new MacBook();
	}

	@Override
	public Phone getPhone() {
		// TODO Auto-generated method stub
		return new Iphone();
	}

}

class SamsungFactory extends Factory {

	@Override
	public PC getPC() {
		// TODO Auto-generated method stub
		return new LapTop();
	}

	@Override
	public Phone getPhone() {
		// TODO Auto-generated method stub
		return new Galaxy();
	}

}


测试:

public class MyTest {
	public static void main(String[] args) throws Exception {
			Factory factory=new AppleFactory();//此处建立苹果工厂
			Phone phone=factory.getPhone();
			PC pc=factory.getPC();
			phone.run();
			pc.run();	
	}
}
打印结果:

Iphone running....
MacBook running...


public class MyTest {
	public static void main(String[] args) throws Exception {
			Factory factory=new SamsungFactory();//此处建立苹果工厂
			Phone phone=factory.getPhone();
			PC pc=factory.getPC();
			phone.run();
			pc.run();	
	}
}
打印结果:

三星Galaxy手机 running...
三星 PC running...

以上实现了手动切换工厂实例,现在将Factory抽象类中加入静态方法getFactory()来读取配置文件

public abstract class Factory {
	abstract PC getPC();

	abstract Phone getPhone();

	static Factory getFactory() throws Exception {
		Properties properties = new Properties();
		properties.load(new FileReader(new File("d:\\properties.config")));
		String factory = properties.getProperty("factory");
		Class clazz = Class.forName(factory);
		return (Factory) clazz.newInstance();
	};
}
配置文件如下:

factory=factoryTest.SamsungFactory

测试:

public class MyTest {
	public static void main(String[] args) throws Exception {
			Factory factory=Factory.getFactory();
			Phone phone=factory.getPhone();
			PC pc=factory.getPC();
			phone.run();
			pc.run();	
	}
}
打印结果:

三星Galaxy手机 running...
三星 PC running...

更改配置文件:

factory=factoryTest.AppleFactory
打印结果:

Iphone running....
MacBook running...

如上实现了,不改变代码而且换工厂以获取不同对象的功能。在实际应用中,工厂调用者并知道phone接口和pc接口的具体实现,只是获取到实例的引用,实现了对不应该暴露给用户资源的隐藏。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值