1. 设计模式概述
设计模式是前人开发过程中总结出来的一套设计经验。这种经验经过软件工程验证后得到广泛认可,能够解决软件开发过程中遇到的问题,在软件工程中应用广泛。
设计模式可以提高代码可复用性、可维护性、可扩展性,正是基于上述优点,很多优秀开源框架、代码内核均使用设计模式,设计模式在软件工程化中使用越来越广泛。
2. 常用的设计模式
设计模式种类很多,通常讲的设计有23种,在这23中设计模式中,更常见的设计模式包含单例模式、简单工厂模式、工厂模式、代理模式、观察者模式等。下面主要对上述5中设计模式做一个详细阐述。
2.1 单例模式
所谓单例,即指某个类在程序运行期间只有单个实例。单例模式会阻止其他对象实例化自己的单例对象的副本,从而确保所有对象都访问唯一实例。
单例模式常见的实现方法有恶汉式、懒汉时、线程安全方式、DCL(Double Check Lock)方式,本文讲的单例模式通过枚举类实现,如下所示:
SingleInstance.java
package com.singleinstance;
public enum SingleInstance {
INSTANCE;
private int count = 0;
public int getCount(){
return count;
}
public void setCount(int count){
this.count = count;
}
}
Main.java
package com.singleinstance;
public class Main {
public static void main(String[] args) {
SingleInstance singleInstance = SingleInstance.INSTANCE;
singleInstance.setCount(999);
System.out.println(singleInstance.getCount());
}
}
程序输出:
999
枚举类型天然具有单例的属性,因为枚举类在编译后就是一个final类,私有的构造函数,下面是SingleInstance.java类编译后的字节码,注意继承关系:
Compiled from "SingleInstance.java"
public final class com.singleinstance.SingleInstance
extends java.lang.Enum<com.singleinstance.SingleInstance> {
public static final com.singleinstance.SingleInstance INSTANCE;
public static com.singleinstance.SingleInstance[] values();
Code:
0: getstatic #1 // Field $VALUES:[Lcom/singleinstance/SingleInstance;
3: invokevirtual #2 // Method "[Lcom/singleinstance/SingleInstance;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[Lcom/singleinstance/SingleInstance;"
9: areturn
public static com.singleinstance.SingleInstance valueOf(java.lang.String);
2.2 简单工厂模式
简单工厂模式可以根据输入条件不同而返回不同属性的产品,灵活切换,简化外部调用方法。
Product.java
package com.simplefactory;
public interface Product {
public static void product();
}
ProductA.java
package com.simplefactory;
public class ProductA implements Product {
public void product(){
System.out.println("ProductA");
}
}
ProductB.java
package com.simplefactory;
public class ProductB implements Product {
public void product(){
System.out.println("ProductB");
}
}
Factory.java
package com.simplefactory;
public class Factory {
public Product getProduct(int id){
switch (id){
case 0:
return new ProductA();
case 1:
return new ProductB();
default:
return null;
}
}
}
Main.java
package com.simplefactory;
public class Main {
public static void main(String[] args) {
ProductA productA = new ProductA();
ProductB productB = new ProductB();
Factory factory = new Factory();
factory.getProduct(0).product();
factory.getProduct(1).product();
}
}
程序输出:
ProductA
ProductB
2.3 工厂模式
Product.java
package com.factory;
public interface Product {
public void product();
}
ProductA.java
package com.factory;
public class ProductA implements Product {
public void product(){
System.out.println("ProductA");
}
}
ProductB.java
package com.factory;
public class ProductB implements Product {
public void product(){
System.out.println("ProductB");
}
}
AbstractFactory.java
package com.factory;
public interface AbstractFactory {
public Product getProduct();
}
FactoryM.java
package com.factory;
public class FactoryM implements AbstractFactory{
public Product getProduct(){
return new ProductA();
}
}
FactoryN.java
package com.factory;
public class FactoryN implements AbstractFactory{
public Product getProduct(){
return new ProductB();
}
}
Main.java
package com.factory;
public class Main {
public static void main(String[] args){
FactoryM factoryM = new FactoryM();
FactoryN factoryN = new FactoryN();
factoryM.getProduct().product();
factoryN.getProduct().product();
}
}
程序输出为:
ProductA
ProductB
简单工厂模式与工厂模式的区别:
简单工厂模式不符合开闭原则,工厂模式符合开闭原则。
2.4 代理模式
Contract.java
public interface Contract {
public void test0();
public void test1();
public void test2();
}
Source.java
public class Source implements Contract {
public void test0(){
System.out.println("test0");
}
public void test1(){
System.out.println("test1");
}
public void test2(){
System.out.println("test2");
}
}
Proxy.java
public class Proxy {
Contract contract;
public Proxy(Contract contract){
this.contract = contract;
}
public void test0(){
contract.test0();
}
public void test1(){
contract.test1();
}
public void test2(){
contract.test2();
}
}
Main.java
public class Main {
public static void main(String[] args){
Source source = new Source();
Proxy proxy = new Proxy(source);
proxy.test0();
proxy.test1();
proxy.test2();
}
}
程序输出:
test0
test1
test2
注意,Proxy类实现代理test方法功能时采用了一个小技巧,通过构造函数注入Source基类,而不是直接通过Proxy与Source类的组合实现test代理,这样可以除去Proxy与Source类强耦合关系。
2.5 观察者模式
观察模式使用很广泛,主要一个目标变化时,快速通知这个目标的观察者,观察者可能存在多个。
观察者模式最常见的一个应用就是Android平台的按钮响应,系统就是通过观察模式实现对按键的监听。
AbstractTarget.java
public interface AbstractTarget {
public void addObserver(Observer obj);
public void removeObserver(Observer obj);
public void notisfyAll(String info);
}
Target.java
import java.util.List;
import java.util.ArrayList;
public class Target implements AbstractTarget {
List<Observer> list = new ArrayList<>();
public void addObserver(Observer obj){
list.add(obj);
}
public void removeObserver(Observer obj){
list.remove(obj);
}
public void notisfyAll(String info){
for (Observer obj : list){
obj.update(info);
}
}
}
Observer.java
public interface Observer {
public void update(String info);
}
FinalObserver.java
public class FinalObserver implements Observer {
String s;
public FinalObserver(String s){
this.s = s;
}
public void update(String info){
System.out.println(s + " " + info);
}
}
Main.java
public class Main{
public static void main(String[] args){
Target target = new Target();
FinalObserver observer0 = new FinalObserver("Observer0");
FinalObserver observer1 = new FinalObserver("Observer1");
FinalObserver observer2 = new FinalObserver("Observer2");
FinalObserver observer3 = new FinalObserver("Observer3");
target.addObserver(observer0);
target.addObserver(observer1);
target.addObserver(observer2);
target.addObserver(observer3);
target.notisfyAll("update");
System.out.println();
target.removeObserver(observer2);
target.notisfyAll("update");
}
}
程序输出为:
Observer0 update
Observer1 update
Observer2 update
Observer3 update
Observer0 update
Observer1 update
Observer3 update
3 总结
设计模式是一种设计经验,是一种代码设计指导思想,有助于代码工程化,但是过犹不及,过度使用设计模式,会使得代码变得臃肿,会给深入研究代码具体实现的阅读者带来一定的困难。因此,具体设计时,可依据场景及需要,适度引入设计模式。