设计模式之见解一

设计模式(Design Patterns

使用设计模式是为了可以重用代码,让代码更加容易被他人理解、保证代码的可靠性。设计模式使得代码编制真正工程化,是软件工程的基石。

在项目中合理的运用设计模式可以完美的解决很多问题,每个模式在现在中都有相应的原理来与之对应。

一、设计模式的分类

总体的来说设计模式有三种类型:

创建型模式:工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式

结构型模式:适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式

行为型模式:策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式

还有两个独立的模式:并发型模式,线程池模式。

 

二、设计模式的原则

1】开闭原则(open Close principle

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以就是说:为了程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。

2】里氏代换原则(Liskov Substitution Principle

里氏代换原则是面向对象设计的基本原则之一。任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石。只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开闭原则”的补充。实现“开闭原则”的关键是抽象化。而基类与子类的继承关系就是抽象化的具体实现。

3】依赖倒转原则(Dependence Inversion Principle

依赖倒转原则是开闭原则的基础,是对接口编程,依赖于抽象而不依赖于具体。

4】接口隔离原则(Interface Segregation Principle

使用多个隔离的接口,比使用单个接口更好。还是一个降低类之间的耦合度,从大型软件架构出发,为了升级和维护方便。降低依赖和耦合度。

5】迪米特原则(最少知道原则)(Demeter Principle

一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6】合成复用原则(Composite Reuse Principle

是尽量使用合成/聚合的方式,而不是使用继承。

 

三、各个模式的运用

1工厂方法模式(Factory Method

工厂方法模式为三种:

普通工厂模式,为建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

 

package com.mjf.model.factory;
 
public interface Send {
 
public void send();
}
package com.mjf.model.factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class MailSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is mail send");
}
 
}
package com.mjf.model.factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class SmsSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is sms send");
}
 
}
package com.mjf.model.factory;
 
/**
 * 工厂类
 * @author h
 *
 */
public class SendFactory {
 
public Send getSend(String type){
if("sms".equals(type)){
return new SmsSender();
}else if("mail".equals(type)){
return new MailSender();
}else{
System.out.println("请选择正确的类型");
return null;
}
}
}
/** 测试类 */
package com.mjf.test.factory;
 
import com.mjf.model.factory.Send;
import com.mjf.model.factory.SendFactory;
 
public class FactoryTest01 {
 
public static void main(String[] args) {
SendFactory send = new SendFactory();
Send s = send.getSend("mail");
s.send();
}
}
 


多个工厂方法模式,是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能创建对象,而多个工厂方法模式是提供多个工厂方法,让他们分别创建对象。

 

package com.mjf.model.factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class MailSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is mail send");
}
 
}
package com.mjf.model.factory;
 
public interface Send {
 
public void send();
}
package com.mjf.model.factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class SmsSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is sms send");
}
 
}
package com.mjf.model.factory;
 
/**
 * 工厂类(多个)
 * @author h
 *
 */
public class SendFactory2 {
 
public Send getSmsSend(){
return new SmsSender();
}
public Send getMailSend(){
return new MailSender();
}
}
/**  测试类 */
package com.mjf.test.factory;
 
import com.mjf.model.factory.Send;
 
import com.mjf.model.factory.SendFactory2;
 
public class FactoryTest02 {
 
public static void main(String[] args) {
SendFactory2 send2 = new SendFactory2();
//Send s = send2.getMailSend();
Send s = send2.getSmsSend();
s.send();
}
}

 使用了多个工厂方法模式后,改进了可以在工厂实现类中添加方法来创建对象。

静态工厂方法模式,是将工厂方法模式里的方法设置为静态的,不需要创建实例可以直接调用。

package com.mjf.model.factory;
 
/**
 * 工厂类(多个)
 * @author h
 *
 */
public class SendFactory3 {
 
public static Send getSmsSend(){
return new SmsSender();
}
public static Send getMailSend(){
return new MailSender();
}
}
/** 测试类 */
package com.mjf.test.factory;
 
import com.mjf.model.factory.Send;
 
import com.mjf.model.factory.SendFactory3;
 
public class FactoryTest03 {
 
public static void main(String[] args) {
//Send s = SendFactory3.getMailSend();
Send s = SendFactory3.getSmsSend();
s.send();
}
}
 

总体来说,工厂模式的作用范围为:出现了很多的对象需要进行创建时,并且用相同的接口。则可以通过工厂方法模式进行创建。

 

2】抽象工厂模式(Abstract Factory 

工厂方法模式有一个问题是,类的创建依赖于工厂类,也就是说,如果要扩展程序就要对工厂类进行修改,违背了开闭原则。

所以采用抽象工厂模式,创建多个工厂类,当增加新的功能,直接增加新的工厂类就行了,而不需要修改原来的代码。

 


package com.mjf.model.abstract_factory;
 
public interface Send {
 
public void send();
}
package com.mjf.model.abstract_factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class MailSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is mail send");
}
 
}
package com.mjf.model.abstract_factory;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class SmsSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is sms send");
}
 
}
package com.mjf.model.abstract_factory;
 
public class SmsFactory implements Provder {
 
@Override
public Send getProduct() {
// TODO Auto-generated method stub
return new SmsSender();
}
 
}
package com.mjf.model.abstract_factory;
 
public class MailFactory implements Provder {
 
@Override
public Send getProduct() {
// TODO Auto-generated method stub
return new MailSender();
}
 
}
package com.mjf.model.abstract_factory;
 
public interface Provder {
 
public Send getProduct();
}
 
/** 测试类 */
package com.mjf.test.abstract_factory;
 
import com.mjf.model.abstract_factory.MailFactory;
import com.mjf.model.abstract_factory.Provder;
import com.mjf.model.abstract_factory.Send;
//import com.mjf.model.abstract_factory.SmsFactory;
 
public class AbstactFactoryTest {
 
public static void main(String[] args) {
//	Provder pro = new SmsFactory();
//	Send product = pro.getProduct();
//	product.send();
Provder pro = new MailFactory();
Send s = pro.getProduct();
s.send();
}
}
 

3】单例模式(singleton抽象工厂模式的好处为:如果你现在想要增加一个功能,发及时信息,则只需要做一个实现类,实现send接口,做一个工厂类,实现provder接口,就可以了;无需去改动现成的代码。扩展性好。

单例对象是一种常用的设计模式。单例对象保证在jvm中,该对象只有一个实例存在。

单例的作用:1)某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销;2)省去了new操作符,降低了系统内存的使用频率,减轻GC的压力;3)有些类好像交易所的核心交易引擎控制交易的流程,如果该类可以创建多个的话,系统就会繁乱。


package com.mjf.model.singleton;
 
public class Singleton {
 
/** 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/** 创建私有化构造方法。防止被初始化 */
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
public Object getResolve(){
return instance;
}
}
 

其实单例模式使用的内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时,这个类的加载过程是线程互斥的。这个类使用是可以实现单例模式,但是存在着线程安全问题。但是,如果使用了synchronize锁定的话,性能会有所下降,当每次调用方法的时候,就会去为对象锁上锁。

package com.mjf.model.singleton;
 
public class Singleton02 {
 
/** 创建私有化构造方法。防止被初始化 */
private Singleton02(){}
/** 创建内部类来实现单例 */
private static class SingletonFactory {
private static Singleton02 instance = new Singleton02();
}
public static Singleton02 getInstance(){
return SingletonFactory.instance;
}
}

单例模式:

1、单例模式理解比较简单,但是实现有点难度。

2、Synchronized关键字锁定的是对象,在用的时候需要注意。

3、单例类比较灵活,毕竟从实现上只是一个普通的Java类,只要满足单例的基本需求,你可以在里面随心所欲的实现一些其它功能,但是静态类不行。从上面这些概括中,基本可以看出二者的区别,但是,从另一方面讲,我们上面最后实现的那个单例模式,内部就是用一个静态类来实现的,所以,二者有很大的关联,只是我们考虑问题的层面不同罢了。两种思想的结合,才能造就出完美的解决方案,就像HashMap采用数组+链表来实现一样,其实生活中很多事情都是这样,单用不同的方法来处理问题,总是有优点也有缺点,最完美的方法是,结合各个方法的优点,才能最好的解决问题!

 

4】建设者模式(Builder


工厂模式提供的时创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象。所谓复合对象就是指某个类具有不同的属性;其实建造者模式就是工厂模式里面的对象创建多个进行管理。

package com.mjf.model.builder;
 
import java.util.ArrayList;
import java.util.List;
 
public class Builder {
 
private List<Send> list = new ArrayList<Send>();
public void produceMailSender(int count){
for(int i=0;i<count;i++){
list.add(new MailSender());
}
}
public void produceSmsSender(int count){
for(int i=0;i<count;i++){
list.add(new SmsSender());
}
}
}
package com.mjf.model.builder;
 
import java.util.ArrayList;
import java.util.List;
 
public class Builder {
 
private List<Send> list = new ArrayList<Send>();
public void produceMailSender(int count){
for(int i=0;i<count;i++){
list.add(new MailSender());
}
}
public void produceSmsSender(int count){
for(int i=0;i<count;i++){
list.add(new SmsSender());
}
}
}
package com.mjf.model.builder;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class MailSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is mail send");
}
 
}
package com.mjf.model.builder;
 
/**
 * 工厂实现类
 * @author h
 *
 */
public class SmsSender implements Send {
 
@Override
public void send() {
// TODO Auto-generated method stub
System.out.println("this is sms send");
}
}
/** 测试类 */
package com.mjf.test.builder;
 
import com.mjf.model.builder.Builder;
 
public class BuilderTest {
 
public static void main(String[] args) {
Builder builder = new Builder();
builder.produceMailSender(10);
}
}


建造者模式将很多的功能集成到一个类里,这个类可以创造出比较复杂的东西。与工厂模式的区别:工厂模式关注的是创建单个产品,而建造者模式则关注创建符合对象。

5】原型模式(Prototype

原型模式的思想是将一个对象作为原型,对其进行复制,克隆,产生一个和原对象类似的新对象。复制对象是通过clone()实现的,实现了Cloneable接口。

package com.mjf.model.prototype;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class Prototype02 implements Cloneable,Serializable {
 
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/** 浅复制 */
public Object clone() throws CloneNotSupportedException{
Prototype02 pro = (Prototype02) super.clone();
return pro;
}
/** 深复制 */
 public Object deepClone() throws IOException, ClassNotFoundException {  
    /* 写入当前对象的二进制流 */  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        ObjectOutputStream oos = new ObjectOutputStream(bos);  
        oos.writeObject(this);  
  
        /* 读出二进制流产生的新对象 */  
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
    ObjectInputStream ois = new ObjectInputStream(bis);  
    return ois.readObject();  
    }  
/** 内部类 */
private class SerializableObject implements Serializable{
 
private static final long serialVersionUID = 1L;
}
 
 
/** setter and getter method */
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
 
public SerializableObject getObj() {
return obj;
}
public void setObj(SerializableObject obj) {
this.obj = obj;
}
}


一个原型类,只需要实现Cloneable接口,复写clone方法,其实cloneable接口是个空接口,所以clone的方法名是随意取的。重点是super.clone()调用的是Objectclone()方法,Objectclonenative的。

浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的,复制的不彻底。

深复制:将一个对象复制后,不论基本数据类型还是引用类型,都是重新创建的。复制的完全更新。

要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值