`話不多說直奔主題。`

目錄
一、工廠設計模式
二、抽象工廠模式
三、單例設計模式
四、建造者(Builder)模式
五、原型模式
六、適配器設計模式
七、橋接(Bridge)設計模式
八、責任鏈模式
九、迭代器設計模式
十、觀察者模式
十一、策略設計模式
一、工廠設計模式
在工廠設計模式中,我們沒有把創(chuàng)建對象暴露給客戶端,而是通過接口的形式創(chuàng)建引入新的對象。接下來我將創(chuàng)建一個Product接口,寫ABC三種產(chǎn)品類 實現(xiàn)接口,它們將會把信息傳遞給ProductFactory,通過ProductFactory來根據(jù)情況獲取產(chǎn)品。
- 1.1 創(chuàng)建一個接口
Product.java
public interface Product {
void product();
}
- 1.2 創(chuàng)建ABC三種產(chǎn)品類 只寫一個A,BC同理。實現(xiàn)Product接口
ProductImplA.java
public class ProductImplA implements Product {
@Override
public void product() {
System.out.println("this is ProductImplA");
}
}
- 1.3 創(chuàng)建工廠類
ProductFactory.java 根據(jù)工廠指定的類型,生成對象。
public class ProductFactory {
public Product getProduct(String productType) {
if (TextUtils.isEmpty(productType)) {
return null;
}
if ("A".equals(productType)) {
return new ProductImplA();
} else if ("B".equals(productType)) {
return new ProductImplB();
} else if ("C".equals(productType)) {
return new ProductImplC();
}
return null;
}
}
- 1.4 使用工廠,通過傳遞的信息獲取具體類的信息
private void FactoryDemo() {
ProductFactory productFactory = new ProductFactory();
productFactory.getProduct("A").product();
productFactory.getProduct("B").product();
productFactory.getProduct("C").product();
}
-1.5 驗證信息
I/System.out: this is ProductImplA
I/System.out: this is ProductImplB
I/System.out: this is ProductImplC
二、抽象工廠模式
抽象工廠是一個大廠,用來創(chuàng)建其他工廠,可以理解為工廠的工廠。
接下來我將創(chuàng)建兩個小廠子Product與Color,與(一)工廠設計模式一樣,接口并實現(xiàn)ABC。之后創(chuàng)建一個抽象工廠類AbstractFactory,將ProductFactory和ColorFactory定義成自擴展的AbstractFactory,之后在創(chuàng)建 工廠創(chuàng)建者FactoryProducer。
- 2.1 照著(一)工廠設計模式寫個Color,Product工廠直接拿來用。
創(chuàng)建一個接口Color.java
public interface Color {
void color();
}
- 2.2 創(chuàng)建ABC三種產(chǎn)品顏色,只寫個A,BC同理 實現(xiàn)Color接口
ColorImplA.java
public class ColorImplA implements Color {
@Override
public void color() {
System.out.println("class ColorImplA , method color");
}
}
- 2.3 創(chuàng)建抽象工廠
AbstractFactory.java
public abstract class AbstractFactory {
public abstract Color getColor(String colorType);
public abstract Product getProduct(String productType);
}
-2.4 創(chuàng)建ColorFactory工廠 注意繼承類,Product同理,但需要注意抽象方法
ColorFactory.java
public class ProductFactory extends AbstractFactory {
@Override
public Color getColor(String colorType) {
return null;
}
@Override
public Product getProduct(String productType) {
if (TextUtils.isEmpty(productType)) {
return null;
}
if ("productA".equals(productType)) {
return new ProductImplA();
} else if ("productB".equals(productType)) {
return new ProductImplB();
} else if ("productC".equals(productType)) {
return new ProductImplC();
}
return null;
}
}
-2.5 創(chuàng)建 創(chuàng)建工廠者, 根據(jù)傳遞信息獲取具體工廠
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getType(String choice) {
if ("color".equals(choice)) {
return new ColorFactory();
} else if ("product".equals(choice)) {
return new ProductFactory();
}
return null;
}
}
- 2.6 使用
private void AbstractFactory() {
AbstractFactory colorProducer = FactoryProducer.getType("color");
colorProducer.getColor("colorA").color();
colorProducer.getColor("colorB").color();
colorProducer.getColor("colorC").color();
AbstractFactory productProducer = FactoryProducer.getType("product");
productProducer.getProduct("productA").product();
productProducer.getProduct("productB").product();
productProducer.getProduct("productC").product();
}
- 2.7驗證信息
I/System.out: class ColorImplA , method color
I/System.out: class ColorImplB , method color
I/System.out: class ColorImplC , method color
I/System.out: class ProductImplA , method product
I/System.out: class ProductImplB , method product
I/System.out: class ProductImplC , method product
三、單例設計模式
Java中最簡單的設計模式之一,這種模式只涉及一個類,它負責創(chuàng)建一個對象,同時保證只有一個對象,這個類提供一種方法來訪問它的唯一對象,可以直接訪問而不需要實例化對象,實例化對象也只有一次。
- 3.1 餓漢式單例
public class SingleClass {
private static SingleClass singleClass = new SingleClass();
public static SingleClass getInstance() {
return singleClass;
}
}
- 3.2懶漢式單例
public class SingleClass {
private static SingleClass singleClass;
public static SingleClass getInstance() {
if (null == singleClass) {
singleClass = new SingleClass();
}
return singleClass;
}
}
四、建造者(Builder)模式
-
建造者模式的UML直觀圖
image.png
核心思想:將復雜對象的構造與表現(xiàn)分離,使同樣的構造可以產(chǎn)生不同的表現(xiàn)。
- 4.1 創(chuàng)建核心抽象類 , 主要就是說把小步驟給抽象出來,通過調用方法來確定都生成什么表現(xiàn)。
AbstractBuilder.java
public abstract class AbstractBuilder {
abstract void InstallStudio();
abstract void DownLoadSDK();
abstract void BuildProject();
public abstract Project getProject();
}
- 4.2 創(chuàng)建Project類, 在這里寫數(shù)據(jù)邏輯
Project.java
public class Project {
private List<String> step = new ArrayList<>();
public void add(String info) {
step.add(info);
}
public void show() {
for (int i = 0; i < step.size(); i++) {
Log.e("step" + (i + 1), "show: " + step.get(i));
}
Log.e("step", "show: 安裝完成!??!");
}
}
- 4.3 為了更直觀表達建造者模式,我把業(yè)務層寫到了一起。
Controller.java
public class Controller extends AbstractBuilder {
private Project project;
public Controller() {
project = new Project();
}
@Override
void InstallStudio() {
project.add("安裝Studio");
}
@Override
void DownLoadSDK() {
project.add("下載SDK");
}
@Override
void BuildProject() {
project.add("build項目");
}
@Override
public Project getProject() {
return project;
}
public static class Builder {
private AbstractBuilder abstractBuilder;
public Builder(AbstractBuilder abstractBuilder) {
this.abstractBuilder = abstractBuilder;
}
public Builder create() {
abstractBuilder.InstallStudio();
abstractBuilder.DownLoadSDK();
abstractBuilder.BuildProject();
return this;
}
public Builder getProject() {
abstractBuilder.getProject();
return this;
}
public Builder show() {
abstractBuilder.getProject().show();
return this;
}
}
}
- 4.4 調用
Controller.Builder builder = new Controller.Builder(new Controller());
builder.create().getProject().show();
- 4.5 驗證信息
step1: show: 安裝Studio
step2: show: 下載SDK
step3: show: build項目
step: show: 編譯完成?。。?
五、原型模式
核心思想:復制粘貼都用過,復制的文件跟原文件沒有一點差別。
概念:用原型實例 指定創(chuàng)建對象的種類,并通過拷貝這些原型創(chuàng)建新的對象。
- 5.1 淺拷貝
只拷貝對象中的基本數(shù)據(jù)類型(8種),對于數(shù)組、容器、引用對象等都不會拷貝 - 5.1.1淺拷貝的代碼實現(xiàn) 創(chuàng)建附件類
AttachType.java
public class AttachType {
**get,set,tostring方法隱藏,但實際有
private String attach;
}
- 5.1.2 定義抽象原型
Student.java
public class Student implements Cloneable {
**get,set,tostring方法隱藏,但實際有
private AttachType attachType;
private String name;
public Student clone() {
Student student = null;
try {
student = (Student) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student;
}
}
- 5.1.3 模擬實現(xiàn)
private void catalog() {
Student student1 = new Student();
AttachType attachType = new AttachType("aaa");
student1.setName("張三");
student1.setAttachType(attachType);
Student student2 = student1.clone();
student2.setName("李四");
student2.getAttachType().setAttach("bbb");
System.out.println(">>>s1" + student1.toString());
System.out.println(">>>s2" + student2.toString());
}
-5.1.4 輸出結果
I/System.out: >>>s1Student{attachType=AttachType{attach='bbb'}, name='張三'}
I/System.out: >>>s2Student{attachType=AttachType{attach='bbb'}, name='李四'}
可以看到只改動了name,AttachType對象,并沒有分離出來。
- 5.2深克隆
拷貝對象中的基本數(shù)據(jù)類型(8種),對于數(shù)組、容器、引用對象等都會拷貝。
深克隆需要注意的是,所有的類,都要實現(xiàn)Cloneable,并且在宿主bean做處理。 - 5.2.1創(chuàng)建附件類
AttachType_2.java
public class AttachType_2 implements Cloneable {
** get,set,tostring方法隱藏,但實際有
private String attach;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
-5.2.2定義抽象原型
Student_2.java
public class Student_2 implements Cloneable {
** get,set,tostring方法隱藏,但實際有
private AttachType attachType;
private String name;
public Student_2 clone() {
Student_2 student_2 = null;
try {
student_2 = (Student_2) super.clone();
student_2.setAttachType((AttachType) student_2.getAttachType().clone());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return (Student_2) student_2;
}
}
- 5.3調用同步5.1.2
- 5.4驗證結果
I/System.out: >>>s1Student{attachType=AttachType{attach='aaa'}, name='張三'}
I/System.out: >>>s2Student{attachType=AttachType{attach='bbb'}, name='李四'}
處理之后,AttachType_2也被拷貝了。
在某種情況下,合理使用可節(jié)省避免不必要的開支。
六、適配器設計模式
概念:負責連接獨立或不兼容的接口。
可分為對象適配和類適配模式。
三個角色,目標接口或類、適配類或接口、適配器
- 對象適配
- 6.1 簡單目標類
目標類處理將語言都轉換成英文,屬于獨立的類。
ConvertEnglish.java
public class ConvertEnglish {
void convertToEnglish(String info) {
System.out.println(">>>轉換成英文 : " + info);
}
}
- 6.1.2 簡單適配接口
需要將我說的漢語都轉換成英語
public interface SpeakChinese {
void speakChinese(String chinese);
}
- 6.1.3 適配器
將功能委托給目標來完成實現(xiàn)。
public class TransformationAdapter implements SpeakChinese {
private ConvertEnglish convertEnglish;
public TransformationAdapter(ConvertEnglish convertEnglish) {
this.convertEnglish = convertEnglish;
}
@Override
public void speakChinese(String chinese) {
convertEnglish.convertToEnglish(chinese);
}
}
- 6.1.4 使用
TransformationAdapter adapter = new TransformationAdapter(new ConvertEnglish());
adapter.speakChinese("我需要轉換成英文");
I/System.out: >>>轉換成英文 : 我需要轉換成英文
對象適配器可以傳入多個不同的對象,用來幫忙處理。
- 類適配
- 6.2.1 還是剛才的類,只需要改動適配器即可
public class TransformationAdapter extends ConvertEnglish implements SpeakChinese {
@Override
public void speakChinese(String chinese) {
super.convertToEnglish(chinese);
}
}
可以看到是通過extends的方式來獲取目標類的屬性,但是java中不支持多繼承,所以在使用類適配的時候,每一個目標類需要單獨寫一個。
七、橋接模式
概念:使得具體實現(xiàn)類和接口實現(xiàn)類獨立。
- 7.1 需要一個接口
Animation.java
public interface Animation {
void onDraw(int radius, int x, int y);
}
- 7.2聲明兩個接口實現(xiàn)類
RotateImpl.java 和 TranslationImpl.java
public class RotateImpl implements Animation {
@Override
public void onDraw(int radius, int x, int y) {
System.out.println(">>>DrawingRotate:" + radius + "," + x + "," + y);
}
}
public class TranslationImpl implements Animation {
@Override
public void onDraw(int radius, int x, int y) {
System.out.println(">>>DrawingTranslation:" + radius + "," + x + "," + y);
}
}
- 7.3 橋梁抽象類
AbstractShape.java
public abstract class AbstractShape {
protected Animation animation;
public AbstractShape(Animation animation) {
this.animation = animation;
}
abstract void onDraw();
}
- 7.4 橋梁具體實現(xiàn)類
ShapeImpl.java
public class ShapeImpl extends AbstractShape {
private int radius, x, y;
public ShapeImpl(int radius, int x, int y, Animation animation) {
super(animation);
this.radius = radius;
this.x = x;
this.y = y;
}
@Override
public void onDraw() {
animation.onDraw(radius, x, y);
}
}
- 7.5使用
ShapeImpl rotate = new ShapeImpl(9, 100, 100, new RotateImpl());
ShapeImpl translate = new ShapeImpl(15, 200, 300, new TranslationImpl());
rotate.onDraw();
translate.onDraw();
···
log
>>>DrawingRotate:9,100,100
>>>DrawingTranslation:15,200,300
使得具體實現(xiàn)類與接口實現(xiàn)類解耦,兩種類都可以在結構上發(fā)生改變并且互不影響。
八、責任鏈模式
概念:將同一請求形成一條鏈,由鏈進行傳遞,能處理的處理,處理不了的繼續(xù)傳遞。
- 8.1 寫個請求bean,用來處理同一類請求
RequestBean.java
public class RequestBean {
** 省略了get set
//小于18歲 大約18歲小于30歲 大于30歲小于60歲的
private String name;
private int age;
private String remark;
{
- 8.2責任鏈抽象類
AbstractHandler.java
public abstract class AbstractHandler {
protected String handlerName;//當前處理的是誰
protected AbstractHandler nextMessage;//捆綁
public AbstractHandler(String handlerName) {
this.handlerName = handlerName;
}
public void setNextMessage(AbstractHandler nextMessage) {
this.nextMessage = nextMessage;
}
public abstract void handlerRequest(RequestBean requestBean);//子類核心處理方法
}
- 8.3 員工ABC 三條處理
StaffA.java
public class StaffA extends AbstractHandler {
public StaffA(String handlerName) {
super(handlerName);
}
@Override
public void handlerRequest(RequestBean requestBean) {
if (requestBean.getAge() < 18) {
System.out.println(">>>由" + this.handlerName + "處理了:" + requestBean.getAge() + "," + requestBean
.getName() + "," + requestBean.getRemark());
} else {
if (this.nextMessage != null) {
this.nextMessage.handlerRequest(requestBean);
}
}
}
}
-8.4 員工B
StaffB.java
public class StaffB extends AbstractHandler {
public StaffB(String handlerName) {
super(handlerName);
}
@Override
public void handlerRequest(RequestBean requestBean) {
if (18 < requestBean.getAge() && requestBean.getAge() < 30) {
System.out.println(">>>由" + this.handlerName + "處理了:" + requestBean.getAge() + "," + requestBean
.getName() + "," + requestBean.getRemark());
} else {
if (this.nextMessage != null) {
this.nextMessage.handlerRequest(requestBean);
}
}
}
}
員工C同理,此處不寫了。
- 8.5 責任關聯(lián)
private void startChain() {
AbstractHandler a = new StaffA("張三");
AbstractHandler b = new StaffB("李四");
AbstractHandler c = new StaffC("王五");
a.setNextMessage(b);
b.setNextMessage(c);
RequestBean request = new RequestBean();
request.setAge(25);
request.setName("趙二");
request.setRemark("無");
a.handlerRequest(request);
}
- 8.6 驗證結果
I/System.out: >>>由李四處理了:25,趙二,無
九、迭代器設計模式
概念:不需要暴露內(nèi)部結構的同時,可以讓外部遍歷數(shù)據(jù)。
- 9.1 構建迭代接口
MyIterator.java 和 Container.java
因為是遍歷我肯定需要知道還有沒有下一條數(shù)據(jù)。
public interface MyIterator {
boolean hasNext();//判定是否有下一條
Object next();
}
public interface Container {
MyIterator getMyIterator();
}
- 9.2迭代類
public class ContainerImpl implements Container {
private String[] strings = new String[]{"aa", "bb", "cc", "dd", "ee"};
@Override
public MyIterator getMyIterator() {
return new Iterator();
}
class Iterator implements MyIterator {
private int index;
@Override
public boolean hasNext() {
if (index < strings.length) {
return true;
}
return false;
}
@Override
public Object next() {
if (this.hasNext()) {
return strings[index++];
}
return null;
}
}
}
hasNext處理我是否還有下一條數(shù)據(jù),在有的前提下我才可以在next方法中return出去,至于為啥要++,next方法肯定在循環(huán)中唄。
- 9.3使用
ContainerImpl container = new ContainerImpl();
for (MyIterator myIterator = container.getMyIterator(); myIterator.hasNext(); ) {
String next = (String) myIterator.next();
System.out.println(">>>next" + next);
}
- 9.4驗證信息
I/System.out: >>>nextaa
I/System.out: >>>nextbb
I/System.out: >>>nextcc
I/System.out: >>>nextdd
I/System.out: >>>nextee
十、觀察者模式
概念:如果一個對象被修改,它的依賴對象將會被自動通知。
自動通知其實就是在 合理的時間調用通知接口,直接上代碼。
- 10.1 抽象類
MyObserver.java
依賴對象會被自動通知?所以 抽象肯定有一個依賴類,一個通知接口
public abstract class MyObserver {
protected Subscriber subscriber;
abstract void update();
}
- 10.2 依賴類
public class Subscriber {
private MyObserver myObserver;
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObserver();
}
//綁定
public void attach(MyObserver myObserver) {
this.myObserver = myObserver;
}
//通知
public void notifyAllObserver() {
myObserver.update();
}
}
可以看到,引入MyObserver抽象類,通過調用MyObserver.update來做通知,所以合理的地方調用notifyAllObserver很重要。
- 10.3 抽象具體類
ObserverImpl.java
public class ObserverImpl extends MyObserver {
public ObserverImpl(Subscriber subscriber) {
this.subscriber = subscriber;
this.subscriber.attach(this);
}
@Override
public void update() {
System.out.println(">>>this update now");
}
}
- 10.4 使用
private Subscriber subscriber;//成員變量,點擊的時候做通知
subscriber = new Subscriber();
new ObserverImpl(subscriber);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
subscriber.setState(1);
}
});
subscriber 寫成了成員變量,在click view的時候,做了setState值更新。更新就是通知該 調用update接口了。
-10.5 驗證信息
I/System.out: >>>this update now
十一、策略設計模式
概念:針對一組算法,將每一種算法都封裝到具有共同接口的獨立的類中,從而是它們可以相互替換。策略模式的最大特點是使得算法可以在不影響客戶端的情況下發(fā)生變化,從而改變不同的功能。
- 11.1 定義共有接口類
IStrategy.java
共有接口類,計算不同的a,b參數(shù)處理方式
public interface IStrategy {
void strategyType(int a, int b);
}
- 11.2 共有接口類ab計算,策略之一
StrategyA.java 加法
public class StrategyA implements IStrategy {
@Override
public void strategyType(int a, int b) {
//處理算法。
int sum = a + b;
System.out.println(">>>sum" + sum);
}
}
- 11.3共有接口類ab計算,策略之一
StrategyB.java 乘法
public class StrategyB implements IStrategy {
@Override
public void strategyType(int a, int b) {
//處理算法。
int sum = a * b;
System.out.println(">>>sum" + sum);
}
}
還寫了個減法,同步上面都一樣。主要是為了表現(xiàn)策略之一。
- 11.4 策略調用類
StrategyImpl.java
public class StrategyImpl {
private IStrategy iStrategy;
public StrategyImpl(IStrategy iStrategy) {
this.iStrategy = iStrategy;
}
public void strategyType(int a, int b) {
iStrategy.strategyType(a, b);
}
}
- 11.5使用
private void strategy() {
int a = 10;
int b = 5;
StrategyImpl strategy = new StrategyImpl(new StrategyA());
strategy.strategyType(a, b);
StrategyImpl strategy2 = new StrategyImpl(new StrategyB());
strategy2.strategyType(a, b);
StrategyImpl strategy3 = new StrategyImpl(new StrategyC());
strategy3.strategyType(a, b);
}
- 11.6驗證信息
I/System.out: >>>sum15
I/System.out: >>>sum50
I/System.out: >>>sum5
策略模式的好處是 實現(xiàn)可以自由切換,擴展性也比較好,閱讀代碼很直觀。
結語
設計模式 真的是可以規(guī)范代碼,并且提高對源碼的理解。
