您的位置:首页 > 编程语言 > Java开发

JAVA 几种常见的设计模式

2015-01-12 23:26 561 查看
一、单例模式
单例设计模式简单说就是无论程序如何运行,采用单例设计模式的类永远只会有一个实例化对象产生。常见方法是将采用单例设计模式的类的构造方法私有化,并在其内部产生该类的实例化对象,并将其封装成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接口的具体实现,只是获取到实例的引用,实现了对不应该暴露给用户资源的隐藏。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: