大話java編程思想

首先提一下java的設計原則:php

1.CHANGE (能應對變化)java

2.KISS(keep it simple &studio 保持代碼簡單的易讀性)設計模式

3.DRY(don't repeat youself 不要寫一些重複的代碼)ide

4.SRP(single responsibility principle 單一職責原則)spa

5.OCP(open closed principle 對外開放,對內封閉).net

6.LSP(liskov substitution principle 里氏置換原則)設計

7.ISP(interface single principle 接口隔離原則)代理

8.DIP(dependence Inversion principle 依賴倒置原則)code

固然,還有其餘不少例如:CARP LOD COC ....blog

關於java的設計原則,網上有不少.能夠參考:http://blog.csdn.net/gaolei1201/article/details/47082783

如今,開始要說的是,在什麼樣的場景下使用他們.

案例:輸出三行 hello World

首先,咱們確定想到的是:

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World");
		System.out.println("Hello World");
		System.out.println("Hello World");
	}
}

如今,需求變化了,客戶但願輸出的是三個Hello Java .那麼怎麼辦呢?修改很簡單,直接複製Java粘貼替換World就能夠.可是,這顯然有問題的,若是輸出是10多二十行呢?那不是要複製粘貼而屢次?這時候,能夠把HelloWorld抽取出來,單獨作一個類.該類提供一個方法,返回HelloWorld語帶代碼:

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println(new A().getStr());
		System.out.println(new A().getStr());
		System.out.println(new A().getStr());
	}
}

class A {
	public String getStr(){
		return "Hello World" ;
	}
}

可是,很明顯.客戶有可能要輸出的是Hello Java ,Hello Html ...顯然,每次都須要修改類A,這就違反了以前的開閉原則.那麼怎麼重構呢?能夠這樣:

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println(new A().getStr(new Java()));
		System.out.println(new A().getStr(new World()));
		System.out.println(new A().getStr(new Html()));
	}
}

class A {
	public String getStr(B b){
		return "Hello "+b.getcontent() ;
	}
}
abstract class B {
	public String getcontent() {
		return setStr() ;
	}
	abstract  String setStr() ;
}

class Java extends B{
	@Override
	String setStr() {
		return "Java";
	}
}

class World extends B {

	@Override
	String setStr() {
		return "World";
	}
}

class Html extends B{

	@Override
	String setStr() {
		return "Html";
	}
}

這樣,下次若是須要PHP的時候,只須要擴展類B 而後返回php就好了,不在須要修改源代碼.這裏每次都須要new Java 很明顯,這裏用以前提到的LSP(里氏替換原則),可是又有一個問題,每次調用都須要去寫實例化代碼,這樣代碼顯的比較的臃腫.也違反了以前提到的SRP(單一職責原則)這時候,咱們採用Java設計模式的代理模式,作一個工廠,工廠傳入一個參數.讓工廠來實例化.因而代碼以下:

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println(new A().getStr(HelloFactory.getInstance("Java")));
		System.out.println(new A().getStr(HelloFactory.getInstance("Html")));
		System.out.println(new A().getStr(HelloFactory.getInstance("World")));
	}
}

class A {
	public String getStr(B b){
		return "Hello "+b.getcontent() ;
	}
}
abstract class B {
	public String getcontent() {
		return setStr() ;
	}
	abstract  String setStr() ;
}

class Java extends B{
	@Override
	String setStr() {
		return "Java";
	}
}

class World extends B {

	@Override
	String setStr() {
		return "World";
	}
}

class Html extends B{

	@Override
	String setStr() {
		return "Html";
	}
}

class HelloFactory {
	public static B getInstance(String str){
		switch (str) {
		case "Java":
			return new Java() ;
		case "Html":
			return new Html() ;
		case "Hello":
			return new World() ;
		default  :
			return null ;
		}
		
	}
}

可是這樣還有一個問題,若是我要新增一個php,那麼工廠類又要從新寫!很明顯,違反了開閉原則.這時候,咱們能夠採用反射機制來實現,代碼以下:

package test.com;

public class HelloWorld {
	public static void main(String[] args) {
		try {
			System.out.println(new A().getStr(HelloFactory.getInstance("Java")));
			System.out.println(new A().getStr(HelloFactory.getInstance("Html")));
			System.out.println(new A().getStr(HelloFactory.getInstance("World")));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class A {
	public String getStr(B b) {
		return "Hello " + b.getcontent();
	}
}

abstract class B {
	public String getcontent() {
		return setStr();
	}

	abstract String setStr();
}

class Java extends B {
	@Override
	String setStr() {
		return "Java";
	}
}

class World extends B {

	@Override
	String setStr() {
		return "World";
	}
}

class Html extends B {

	@Override
	String setStr() {
		return "Html";
	}
}

class HelloFactory {
	public static B getInstance(String str) throws Exception {
		// 這裏採用的是包名+類名形式,由於我這個類是在test.com包下.
		return (B) Class.forName("test.com." + str).newInstance();
	}
}

如今能夠直接新增一個php的類,而後經過工廠來實例化了.可是,這裏還有一個問題,若是是第三方使用個人方法來輸出Hello World ,那麼每次第三方要新增的時候,我都要去修改個人源代碼...oh,no!!必須重構~~,那麼採用接口方式吧,把控制權給到第三方(使用我代碼開發的人):

package test.com;

public class HelloWorld {
	public static void main(String[] args) {
		try {
			System.out.println(new A().getStr(HelloFactory.getInstance("Java")));
			System.out.println(new A().getStr(HelloFactory.getInstance("Html")));
			System.out.println(new A().getStr(HelloFactory.getInstance("World")));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class A {
	public String getStr(B b) {
		return "Hello " + b.getcontent();
	}
}

interface B {
	public String getcontent();
}

class Java implements B {

	public String getcontent() {
		return "Java";
	}
}

class World implements B {
	@Override
	public String getcontent() {
		return "World";
	}
}

class Html implements B {
	@Override
	public String getcontent() {
		return "Html";
	}
}

class HelloFactory {
	public static B getInstance(String str) throws Exception {
		// 這裏採用的是包名+類名形式,由於我這個類是在test.com包下.
		return (B) Class.forName("test.com." + str).newInstance();
	}
}

如今,第三方使用個人程序的時候,只須要實現我提供的接口B,就能夠了.再也不依賴我去修改我本身的程序了.可是,若是我要想輸出的是Java Hello,或者就是Html這樣的格式的時候呢? 不是還須要修改個人代碼麼?因此,我必須把更多的控制權給到使用者(第三方).:

package test.com;

public class HelloWorld {
	public static void main(String[] args) {
		try {
			System.out.println(HelloFactory.getInstance("Java").getStr(n->{
				return n+" Hello" ;
			}));
			System.out.println(HelloFactory.getInstance("Html").getStr(n->{
				return n+" is too hard" ;
			}));
			System.out.println(HelloFactory.getInstance("World").getStr(n->{
				return n+" is open" ;
			}));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

abstract class A {
	public String getStr(C c) {
		return c.setStr(getName()) ;
	}
	abstract String getName() ;
}

interface C {
	public String setStr(String str);
}

class Html extends A {

	@Override
	String getName() {
		return "Html";
	}
}
class Java extends A {
	
	@Override
	String getName() {
		return "Java";
	}
}
class World extends A {
	
	@Override
	String getName() {
		return "World";
	}
}


class HelloFactory {
	public static A getInstance(String str) throws Exception {
		// 這裏採用的是包名+類名形式,由於我這個類是在test.com包下.
		return (A) Class.forName("test.com." + str).newInstance();
	}
}

這樣,第三方想要什麼格式的都有了.可是這裏還有一個問題,若是我不實用Java,而要使用php的時候,每次都要實現抽象類,而後使用匿名接口,而後再從新編譯.那麼若是作成配置文件,是否是就再也不須要從新編譯了呢?因而能夠改寫:

package test.com;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

public class HelloWorld {
	public static void main(String[] args) {
		Properties properties = new Properties();

		try {
			InputStream inputStream = new BufferedInputStream(new FileInputStream("src/test/com/mySet.properties"));
			properties.load(inputStream);
			System.out.println(HelloFactory.getInstance(properties.getProperty("key1").toString()).getStr(n -> {
				return n + " Hello";
			}));
			System.out.println(HelloFactory.getInstance(properties.getProperty("key2").toString()).getStr(n -> {
				return n + " Hello";
			}));
			System.out.println(HelloFactory.getInstance(properties.getProperty("key3").toString()).getStr(n -> {
				return n + " Hello";
			}));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

abstract class A {
	public String getStr(C c) {
		return c.setStr(getName());
	}

	abstract String getName();
}

interface C {
	public String setStr(String str);
}

class Html extends A {

	@Override
	String getName() {
		return "Html";
	}
}

class Java extends A {

	@Override
	String getName() {
		return "Java";
	}
}

class World extends A {

	@Override
	String getName() {
		return "World";
	}
}

class HelloFactory {
	public static A getInstance(String str) throws Exception {
		// 這裏採用的是包名+類名形式,由於我這個類是在test.com包下.
		return (A) Class.forName("test.com." + str).newInstance();
	}
}

配置文件(mySet.properties):

key1=Java
key2=Html
key3=World

到這裏,若是第三方想要輸出什麼格式,均可以自由發揮.想要輸出php只需修改配置文件就能夠了.也不須要再對個人代碼驚醒從新編譯.貌似比較完善了..

可是,真的這樣嗎?

如今,寫了這麼多代碼,可是好像我什麼都沒作...要實現什麼樣的輸出,都須要去先實現個人抽象類,而後在修改配置文件.我什麼都沒作啊,貌似.可是,比起最初的版本,我實際確實作了太多的工做,那麼該不應如此作呢?例如客戶只須要輸出一個Hello World,而你卻給我如此一大堆,最還要我本身寫一大堆實現類,配置.就爲了一個Hello World? 確定有病!!

因此,這就是代碼的另外一個原則YAGNI(You Ain’t Gonna Need It     你是否是真的須要它!) 我理解爲中庸,儒家思想嘛.

對於Java思想來講,這只是冰山一角.自我勉勵吧.

相關文章
相關標籤/搜索