1、开闭原则

        开闭原则,准确一点说,是开放封闭原则,意思是对内开放,对外封闭。如果我们能够熟悉JAVA语言的三大特性(当然,也有人说是四大),那么我们就会很容易理解这里的内外,否则就可能有些摸不着头脑了。

        用程序来说,就是对扩展开放,这个设计是可以扩展的;对修改封闭,程序在扩展的时候,不需要修改原有的设计,体现了很好的扩展性和封装性。


2、两个特征

遵循开闭原则设计出的模块具有两个主要特征:

对于扩展是开放的(Open for extension),这就需要我们设计的软件是可以扩展的,不仅仅局限于当前这一种情景下。

对于修改是关闭的(Closed for modification),这是说当我们进行扩展的时候,是不需要更改原有的代码的,保证了之前代码的完整性。


3、场景举例

        对于开闭原则,简单使用这样的理论,可能会比较枯燥,也不那么容易理解。举例说明我们生活中常见的场景,比如,当我们出门旅游,有一个同伴走丢了,我们要找他,向路人问路的时候,会描述,这人多大年纪,多高,胖还是瘦。经常看到在派出所录口供的场景,我们会突然想起一些其它的特征,比如,这人是左撇子,眼睛是碧绿色的等等。

        在我们前面的描述中,这个人是一种状态,当我们再添加一个特征的时候,我们只需要在口供之后添加一些特征即可,不必要重新再从头写一遍。开闭原则也是这样的,可能这样举例还是太过于抽象,那么我们用一段代码来说明。


4、代码示例

这里提供一个找人的接口,对应第一个描述:

/**
 * 找人
 * @author ljtyzhr
 *
 */
public interface FindPerson {
	/**
	 * 年龄  
	 * @return
	 */
    public int getAge();
    
    /**
     * 名字
     * @return
     */
    public String getName();
    
    /**
     * 长相
     * @return
     */
    public String getFace();
}

然后是一个实体类,对应我们的张贴公告:

/**
 * 寻找一个男人
 * @author ljtyzhr
 *
 */
public class FindMan implements FindPerson{
	
	private String name;  
        private int age;  
        private String face;  
       
        public FindMan(String name, int age, String face){  
            this.name = name;  
            this.age = age;  
            this.face = face;  
        } 

	@Override
	public int getAge() {
		// TODO Auto-generated method stub
		return this.age;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return this.name;
	}

	@Override
	public String getFace() {
		// TODO Auto-generated method stub
		return this.face;
	}
	
}

这个时候,我们就完成了这个第一个描述的代码,可以测试一下,如下:

import java.util.ArrayList;

/**
 * 测试方法
 * @author ljtyzhr
 *
 */
public class MainClass {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		ArrayList<FindMan> lists = new ArrayList<FindMan>();
		
		lists.add(new FindMan("李四", 20, "方型"));
		lists.add(new FindMan("张三", 21, "圆型"));
		
		for(FindMan man:lists){  
                    System.out.println("姓名:"+man.getName()+" 年龄:"+man.getAge()+"  长相:"+man.getFace());  
                }
	}

}

5、扩展方法

        刚才,我们在测试方法找的是张三、李四,如果这个时候,我们想起来,今天找的这个人,他是一个外国人,会不会好找得多了呢?我们该怎么改我们写好的告示?如何扩展?首先,我们来一个扩展的接口,继承刚才的找人接口,只不过现在我们是添加一个方法,变成了找外国人。如下:

/**
 * 外国男人
 * @author ljtyzhr
 * 
 */
public interface ForeignerMan extends FindPerson{
	/**
	 * 国籍
	 * @return
	 */
	public String getCountry();
}

然后与上面一样,我们示例化一个类,这个类实现了找外国人的接口,如下:

public class FindForeigner implements ForeignerMan {
	
	private String name;  
    private int age;  
    private String country;  
    private String face;  
    
    public FindForeigner(String name, int age, String country, String face){  
        this.name = name;  
        this.age = age;  
        this.country = country;  
        this.face =face;  
    } 

	@Override
	public int getAge() {
		// TODO Auto-generated method stub
		return this.age;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return this.name;
	}

	@Override
	public String getFace() {
		// TODO Auto-generated method stub
		return this.face;
	}

	@Override
	public String getCountry() {
		// TODO Auto-generated method stub
		return this.country;
	}

}

最后的测试案例,如下:

// 分割线
		ForeignerMan man = new FindForeigner("David", 23, "England", "瘦长");
		System.out.println("姓名:"+man.getName()+" 年龄:"+man.getAge()+  
                    "  长相:"+man.getFace() + " 国籍:" + man.getCountry());
	

这样,我们在不修改原有代码的前提下,进行了扩展。这就是开闭原则提倡的设计原则。



更多推荐