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

JAVA常用设计模式

2015-04-04 15:13 375 查看
很多人在学习设计模式,感觉定义很抽象,包括我,这也难怪JAVA本来就是一种抽象的思想,所以写了这篇博客,加入我自己的理解,难免会有一些不合理的地方,希望大家批评指正。

首先说说设计模式是什么吧。简单的来说,设计模式是一个经验的总结,与具体的语言无关,相当于一个模型,可以被不同的语言反复使用,本文以JAVA语言为基础。

一、要明白具体的设计模式,我们就需要知道设计模式做了什么,具体原则是什么

1. 单一职责:简单的说,就是每个类需要做的事情尽量少,最好是一件
2. 开闭原则:把经常变得东西抽象成一个模板,变化的部分只提供一个方法,具体的细节由子类实现,即别人想添加功能,只需要添加一个子类,而无需修改源码的实现。
3. 里氏替换:这个我们应该很熟悉,就是一种继承的理念,即继承父类的子类们中,应该具有一些共同的行为特征和属性,比如不能定义一个Person类,让Pig继承。
4. 依赖注入原则:也是一种分离思想,即子类对象依赖于抽象类,而不是依赖具体实现类
5. 接口分离原则:一个接口的功能要满足单一原则,因为接口的实现,必须重写接口的方法,所以接口的抽象方法不宜过多。
6. 迪米特原则:对象与对象之间的关系要少,比如一个对象尽量不要去调用另一个对象的方法。
7. 总结,虽然是用自己的话在表述,但自己也不知道自己在写什么。


二、接下来,我想介绍一些常用的设计模式

█ 简单工厂设计模式:类的创建由工厂类去实现,比如我需要实现一个水果工厂,别人需要什么水果,我就提供什么

第一步:创建工厂类


public class FruitFactory {

public static Fruit createFruit(String fruitType)
{
if("apple".equals(fruitType)){
return new Apple();
}else if("banana".equals(fruitType))
{
return new Banana();
}else{
return null;
}
}
}


第二步:水果接口


public abstract class Fruit {
public abstract void taste();
}


第三步:创建需要添加的具体水果
1. 造苹果


public class Apple extends Fruit {

@Override
public void taste() {
// TODO Auto-generated method stub
System.out.println("苹果味道有点酸!");
}
}


2. 造香蕉


public class Banana extends Fruit {

@Override
public void taste() {
// TODO Auto-generated method stub
System.out.println("香蕉味道很甜!");
}
}


第四步:具体实现造水果


public class FruitDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub
Fruit fruit = FruitFactory.createFruit("apple");//要苹果?造一个!
fruit.taste();
a = AnimalFactory.createAnimal("banana");//要香蕉?造一个!
fruit.taste();
}
}


第五步:总结

从上面的代码,得知,水果工厂内只有apple和banana,但如果客户需要橘子,怎么办?这还不简单?so easy。


public class FruitFactory {

public static Fruit createFruit(String fruitType)
{
if("apple".equals(fruitType)){
return new Apple();
}else if("banana".equals(fruitType))
{
return new Banana();
}else if("orange".equals(fruitType))
{
return new Orange();
else{
return null;
}
}
}


但还需要橙子,梨子,桃子呢?所以缺点总结如下
1. 有新的需求,工厂类就必须不断修改,麻烦!所以出现了工厂类。下面介绍工厂类。


█ 工厂模式:在简单工厂类的基础上,添加了小工厂,就好像有一个水果工厂,还添加一个子工厂,专门造苹果,另一个子工厂专门造香蕉,这样,新的需求只需添加一个需求类实现水果工厂接口即可,废话不多说,看代码。

第一步:创建大工厂类接口


public interface Factory {
public abstract Fruit createFruit();
}


第二步:创建水果类


public abstract class Fruit {
public abstract void taste();
}


第三步:创建具体水果的小工厂类,实现大工厂接口
1. 苹果工厂


public class AppleFactory implements Factory {

@Override
public Fruit createFruit() {
// TODO Auto-generated method stub
return new Apple();
}
}


2. 香蕉工厂


public class BananaFactory implements Factory {

@Override
public Fruit createFruit() {
// TODO Auto-generated method stub
return new Banana();
}
}


第四步:造水果,继承水果类

1. 造苹果


public class Apple extends Fruit {
@Override
public void taste() {
// TODO Auto-generated method stub
System.out.println("苹果味道有点酸!");
}

}


造香蕉

public class Banana extends Fruit {

@Override
public void taste() {
// TODO Auto-generated method stub
System.out.println("香蕉味道很甜!");
}
}


第五步:测试类


public class FruitDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub
//苹果
Factory factory = new AppleFactory();
Fruit fruit = factory.creatFruit();
System.out.println(fruit.taste);

//香蕉
factory = new BananaFactory();
Fruit fruit = factory.creatFruit();
System.out.println(fruit.taste);
}
}


第六步:总结


优点:每增加一个需求,只需增加一个具体类,和具体类的工厂类,而无需改动原有的代码。

缺点:工作量较大,看着都累。

█ 单例设计模式:简单的来说,就是不允许外部创建对象,而是直接使用,那么如何实现不让外界创建对象,而且还可以使用对象呢?

- 将被使用类的构造方法私有化,即private修饰

- 在类的成员位置创建对象

- 创建公有方法getObject,让外界能够使用

单例设计模式——-饿汉式:就是立即创建对象

public class Fruit {

private Fruit()
{
//构造方法使用private修饰
}
//创建Fruit对象
static Fruit fruit = new Fruit();
//通过公有属性方法返回对象给外界
public static Fruit getFruit()
{
return fruit;
}
}


测试


public class FruitDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

Fruit.fruit = null;
Fruit fruit = Fruit.getFruit();
}
}


单例设计模式——-懒汉式:不立即创建对象,而是延后到被调用时

public class Fruit {

private Fruit()
{
//构造方法使用private修饰
}
//创建Fruit对象
static Fruit fruit = null;
//通过公有属性方法返回对象给外界
public static Fruit getFruit()
{
if(fruit == null)
{
fruit = new Fruit();
}
return fruit;
}
}


测试


public class FruitDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub

Fruit.fruit = null;
Fruit fruit = Fruit.getFruit();
}
}


单例设计模式——总结

在实际应用中会选择饿汉式,因为懒汉式存在安全隐患,在多线程时,多个线程同时获取该对象时,会出现对象具体的创建混乱。解决办法如下:同步方法。

public class Fruit {

private Fruit()
{
//构造方法使用private修饰
}
//创建Fruit对象
static Fruit fruit = null;
//通过公有属性方法返回对象给外界,注意添加synchronized,实现线程的同步
public synchronized static Fruit getFruit()
{
if(fruit == null)
{
fruit = new Fruit();
}
return fruit;
}
}


█ 模版设计模式:定义一个算法的骨架,这个骨架就是一个模版,具体的算法实现推迟到子类中,比如我们计算算法运行的效率,我们就可以把计算效率提取成一个模版,而具体的算法我们可以到子类中实现,而无需改动模版。

第一步:定义一个模版


public abstract class Pattern {
public long getTime(){
long startTime = System.currentTimeMillis();
methodPattern();//只需实现这个抽象方法来实现具体的算法即可
long endTime = System.currentTimeMillis();
return endTime-startTime;
}
public abstract void methodPattern();
}


第二步:实现具体的算法,这里选择快速排序,其他的就不一一举例


public class ForTest extends Pattern {

//排序
public static void Sort(int[] arr,int low,int high)
{
if(low < high)
{
int position = getPositionSort(arr,low,high);
Sort(arr,low,position-1);
Sort(arr,position+1,high);
}
}
private static int getPositionSort(int[] arr, int low, int high) {
// TODO Auto-generated method stub
int temp = arr[low];
while(low < high)
{
while(low < high && arr[high]>temp)
high--;
arr[low] = arr[high];
while(low < high && arr[low] < temp)
low++;
arr[high] = arr[low];
}
arr[low] = temp;
return low;
}
//主要是这个构造方法的重写
@Override
public void methodPattern() {
// TODO Auto-generated method stub
int arr[] = {12,3,2,30,10};

Sort(arr,0,arr.length-1);
for(int s_arr:arr)
{
System.out.print(s_arr+" ");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息